Python TKinter窗口中基于时钟的方法 - 请批判

时间:2012-08-15 03:21:53

标签: python tkinter countdown

目标:30分钟的定时活动,循环通过一系列交替的缓慢和激烈的练习。窗口从30分钟开始显示倒数计时器开始。练习以30秒的“慢”活动开始 - 计时器下方显示“慢”字样。然后继续进行60秒的剧烈运动。然后是30秒的慢节奏,接着是60秒的不同剧烈运动,依此类推。总共有4种不同的激烈运动,每种运动都以缓慢的速度交替。

我已经汇编了下面的代码。我不相信它是直观的。我不喜欢在方法之间蹦蹦跳跳,我觉得有一些方法可以用来提高效率。在实际水平上,这不能很好地工作,因为计时器和消息(即显示的慢/运动#)开始变得不同步。我已经研究了python博客并且继续“听到”关于Tkinter没有多线程的东西。我猜测,当倒计时线程占用资源时,后(x,y)会受到损害....不太确定。另外,我想在每个方法之后添加一个音调作为“运动员”的音频队列无论如何,提前感谢查看我的原始代码。

 import Tkinter as tk

 class ExampleApp(tk.Tk):
     def __init__(self):
         tk.Tk.__init__(self)
         self.label = tk.Label(self, text="", width=10, font= ("Helvetica",72), background='yellow', fg = 'red')
         self.label2 = tk.Label(self, text="", width=10, font=("Helvetica",72), background='yellow', fg = 'blue')
         self.label.pack()
         self.label2.pack()
         self.remaining = 0
         self.countdown(1800)  # the 30 minutes countdown  initialization
         self.run = True 

     def countdown(self, remaining = None):
         if self.remaining == 1799:  # marker that starts the methods series
             self.start()
         if remaining is not None:
             self.remaining = remaining
         if self.remaining >= 1:
             mins = int(self.remaining/60)
             #rsecs = self.remaining - mins * 60 #could use this
             rsecs = self.remaining % 60     #same results as t - mins * 60
             self.remaining = self.remaining -1
             self.after(1000, self.countdown)
             self.label.configure(text ="%.2f" % (mins + rsecs / 100.0))
         else:
             self.label.configure(text="Stop")

     def start(self):
         app.after(0, self.slow1)
         return

     def slow1(self):
         self.label2.configure(text="Slow" )
         app.after(30000, self.fast1)
         return

     def fast1(self):
         self.label2.configure(text="Exercise 1" )
         app.after(61000, self.slow2)
         return

     def slow2(self):
         self.label2.configure(text="Slow" )
         app.after(31000, self.fast2)
         return

     def fast2(self):
         self.label2.configure(text="Exercise 2" )
         app.after(61000, self.slow3)
         return

     def slow3(self):
         self.label2.configure(text="Slow" )
         app.after(30000, self.fast3)
         return

     def fast3(self):
         self.label2.configure(text="Exercise 3" )
         app.after(60000, self.slow4)
         return

     def slow4(self):
         self.label2.configure(text="Slow" )
         app.after(30000, self.fast4)
         return

     def fast4(self):
         self.label2.configure(text="Exercise 4" )
         app.after(60000, self.slow1)
         return

 if __name__ == "__main__":
     app = ExampleApp()
     app.title("Intense Workout")
     app.geometry('550x550+200+200')
     app.configure(background='yellow')
     app.mainloop()

1 个答案:

答案 0 :(得分:1)

有很多方法可以解决这个问题,而且你不需要线程。这是一个想法:

从定义间隔的数据结构开始。例如:

intervals = [[30, "slow"], [60, "intense"], [30, "slow"], [60, "intense]]

接下来,设置一个每秒调用一次的简单计时器功能。在每一秒,它显示列表头部的数字和字符串。数字代表剩下的时间。在该计时器功能中,从数字中减去1。如果它变为零,则从列表中删除该元素。让这个函数稍后使用after调用自己,在数据结构变空时停止(即:当只剩下一对并且数字下降到零时)。

以下内容为您提供了有关如何实现此功能的建议。代码可以做得更好,但重点是说明如何使用after迭代数据结构,而不是必须提供生产质量示例。

import Tkinter as tk

class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.label = tk.Label(self, text="", width=10, font= ("Helvetica",72), background='yellow', fg = 'red')
        self.label2 = tk.Label(self, text="", width=10, font=("Helvetica",72), background='yellow', fg = 'blue')
        self.label.pack()
        self.label2.pack()
        self.intervals = [[30, "Slow"], [60, "Exercise 1"],
                          [30, "Slow"], [60, "Exercise 2"],
                          [30, "Slow"], [60, "Exercise 3"],
                          [30, "Slow"], [60, "Exercise 4"],
                          ]
        self.countdown()

    def countdown(self):
        (remaining, label) = self.intervals[0]
        self.label.configure(text=remaining)
        self.label2.configure(text=label)
        remaining -= 1
        if remaining < 0:
            self.intervals.pop(0)
        else:
            self.intervals[0][0] = remaining
        if len(self.intervals) > 0:
            self.after(1000, self.countdown)
        else:
            self.label.configure(text="Done!")

if __name__ == "__main__":
    app = ExampleApp()
    app.title("Intense Workout")
    app.geometry('550x550+200+200')
    app.configure(background='yellow')
    app.mainloop()