2017-08-02 90 views
0

我试图做一个番茄钟计时器,它将显示不同的倒计时三个按钮选项之一的点击。设置tkinter标签显示倒数计时器

这里的问题是,每次我点击一个按钮后,先前点击一个按钮,该标签挣扎与显示哪个定时器。它试图同时显示两个计时器倒计时。

我需要标签停止显示第一个按钮的计时器倒计时,当我点击另一个按钮。这里是我的代码:

from tkinter import * 

class Application(Frame): 
    def __init__(self,master): 
     super(Application,self).__init__(master) 
     self.pack() 
     self.createWidgets() 

    def createWidgets(self): 

     self.labelvariable = StringVar() 
     self.labelvariable.set("25:00") 

     self.thelabel = Label(self,textvariable = self.labelvariable,font=('Helvetica',50)) 
     self.thelabel.pack(side=TOP) 

     self.firstButton = Button(self,text="pomodoro",command=self.pomodoro) 
     self.firstButton.pack(side=LEFT) 

     self.secondButton = Button(self,text="short break",command=self.shortBreak) 
     self.secondButton.pack(side=LEFT) 

     self.thirdButton = Button(self,text="long break",command=self.longBreak) 
     self.thirdButton.pack(side=LEFT) 

    def pomodoro(self): 
     countdown(1500) 

    def shortBreak(self): 
     countdown(300) 

    def longBreak(self): 
     countdown(600) 





def countdown(timeInSeconds): 
    mins,secs = divmod(timeInSeconds,60) 
    timeformat = "{0:02d}:{1:02d}".format(mins,secs) 
    app.labelvariable.set(timeformat) 
    root.after(1000,countdown,timeInSeconds-1) 



if __name__ == '__main__': 
    root = Tk() 
    root.title("Timer") 
    app = Application(root) 
    root.mainloop() 
+2

使用after_cancel()取消前()调用之后http://effbot.org/tkinterbook/widget.htm我建议您等待像1/10秒,并发出另一个after_cancel( ),以防在程序在函数中,但在after()语句之上的地方点击。 –

回答

0

这里是一个可能的解决方案。这个将countdown函数移入Application类,并使其自由运行。然后,我添加了一个类属性来跟踪当前剩余时间,并将其减少到0.这样做的缺点是可能需要几秒钟来显示新的计数。

from tkinter import * 
from threading import Event 

class Application(Frame): 
    def __init__(self,master): 
     super(Application,self).__init__(master) 
     self.pack() 
     self.createWidgets() 
     self._count = 0 
     self.countdown() 

    def createWidgets(self): 

     self.labelvariable = StringVar() 

     self.thelabel = Label(self,textvariable = self.labelvariable,font=('Helvetica',50)) 
     self.thelabel.pack(side=TOP) 

     self.firstButton = Button(self,text="pomodoro",command=self.pomodoro) 
     self.firstButton.pack(side=LEFT) 

     self.secondButton = Button(self,text="short break",command=self.shortBreak) 
     self.secondButton.pack(side=LEFT) 

     self.thirdButton = Button(self,text="long break",command=self.longBreak) 
     self.thirdButton.pack(side=LEFT) 

    def pomodoro(self): 
     self._count = 1500 

    def shortBreak(self): 
     self._count = 300 

    def longBreak(self): 
     self._count = 600 

    def countdown(self): 
     mins,secs = divmod(self._count,60) 
     timeformat = "{0:02d}:{1:02d}".format(mins,secs) 
     app.labelvariable.set(timeformat) 
     if self._count > 0: 
      self._count -= 1 
     root.after(1000,self.countdown) 



if __name__ == '__main__': 
    root = Tk() 
    root.title("Timer") 
    app = Application(root) 
    root.mainloop() 

这是基于卷毛乔的comment另一种选择。这一个使用after_cancel通过取消下一个警报来停止当前正在运行的倒计时。它的好处是新的倒计时立即开始。

from tkinter import * 


class Application(Frame): 
    def __init__(self,master): 
     super(Application,self).__init__(master) 
     self.pack() 
     self.createWidgets() 
     self._alarm_id = None 

    def createWidgets(self): 

     self.labelvariable = StringVar() 
     self.labelvariable.set("25:00") 

     self.thelabel = Label(self,textvariable = self.labelvariable,font=('Helvetica',50)) 
     self.thelabel.pack(side=TOP) 

     self.firstButton = Button(self,text="pomodoro",command=self.pomodoro) 
     self.firstButton.pack(side=LEFT) 

     self.secondButton = Button(self,text="short break",command=self.shortBreak) 
     self.secondButton.pack(side=LEFT) 

     self.thirdButton = Button(self,text="long break",command=self.longBreak) 
     self.thirdButton.pack(side=LEFT) 

    def pomodoro(self): 
     if self._alarm_id is not None: 
      self.master.after_cancel(self._alarm_id) 
     self.countdown(1500) 

    def shortBreak(self): 
     if self._alarm_id is not None: 
      self.master.after_cancel(self._alarm_id) 
     self.countdown(300) 

    def longBreak(self): 
     if self._alarm_id is not None: 
      self.master.after_cancel(self._alarm_id) 
     self.countdown(600) 

    def countdown(self, timeInSeconds): 
     mins,secs = divmod(timeInSeconds, 60) 
     timeformat = "{0:02d}:{1:02d}".format(mins, secs) 
     app.labelvariable.set(timeformat) 
     self._alarm_id = self.master.after(1000, self.countdown, timeInSeconds-1) 


if __name__ == '__main__': 
    root = Tk() 
    root.title("Timer") 
    app = Application(root) 
    root.mainloop() 
+0

没有理由做'self.after(0,self.countdown)'。直接调用它:'self.countdown()'。 –

+0

这太好了。非常感谢大家 –

+0

@BryanOakley这是一个很好的观点。我使用'后'来推迟实际运行'倒计时',直到主循环开始。不过,这种情况的好处是微不足道的。 – FamousJameous