设置tkinter标签以显示倒数计时器

时间:2017-08-02 21:07:31

标签: python 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()

1 个答案:

答案 0 :(得分:0)

这是一种可能的解决方案。这个将countdown函数移动到Application类中并使其自由运行。然后我添加了一个class属性来跟踪剩下的当前时间,然后将其减少到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()

这是另一个基于Curly Joe 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()