使用Tkinter中的倒数计时器启动和暂停

时间:2017-12-15 00:08:47

标签: python python-3.x tkinter

 import tkinter as tk

class Timer:
    def __init__(self, master):
        self.master = master
        master.title("Pomodoro Timer")

        self.state = False
        self.minutes = 25
        self.seconds = 0

        self.display = tk.Label(master, height=10, width=10, textvariable="")
        self.display.config(text="00:00")
        self.display.grid(row=0, column=0, columnspan=2)

        self.start_button = tk.Button(master, bg="Green", activebackground="Dark Green", text="Start", width=8, height=4, command=self.start())
        self.start_button.grid(row=1, column=0)

        self.pause_button = tk.Button(master, bg="Red", activebackground="Dark Red", text="Pause", width=8, height=4, command=self.pause())
        self.pause_button.grid(row=1, column=1)

        self.countdown()

    def countdown(self):
        """Displays a clock starting at min:sec to 00:00, ex: 25:00 -> 00:00"""
        mins = self.minutes
        secs = self.seconds

        if self.state == True:
            if secs < 10:
                if mins < 10:
                    self.display.config(text="0%d : 0%d" % (mins, secs))
                else:
                    self.display.config(text="%d : 0%d" % (mins, secs))
            else:
                if mins < 10:
                    self.display.config(text="0%d : %d" % (mins, secs))
                else:
                    self.display.config(text="%d : %d" % (mins, secs))

            if (mins == 0) and (secs == 0):
                self.display.config(text="Done!")
            else:
                if secs == 0:
                    mins -= 1
                    secs = 59
                else:
                    secs -= 1

                self.master.after(1000, self.countdown())

        elif self.state == False:
            self.master.after(100, self.countdown())

    def start(self):
        if self.state == False:
            self.state = True

    def pause(self):
        if self.state == True:
            self.state = False



root = tk.Tk()
my_timer = Timer(root)

root.mainloop()

一般来说,对于Python来说是个新手,我试图制作一个本质上具有开始和暂停功能的简单倒数计时器。

我认为可行的方法是在窗口启动时调用倒计时功能,让它通过递归调用不断检查窗口的“状态”。当“状态”为False时,倒计时功能将跳过倒计时功能的“计时器”部分并再次调用它以查看“状态”是否已更改。

当用户点击开始按钮时,“状态”将变为True,倒计时功能现在会看到“状态”已经改变,然后开始实际倒计时。

然后当用户点击暂停按钮时,“状态”将再次变为False,倒计时功能将再次跳过该功能的“计时器”部分,然后再次调用它。

我一直遇到的问题是:

RecursionError: maximum recursion depth exceeded in comparison

我不知道如何通过我目前的实现来解决这个错误。

修改

因此,在两个实例(不在init下)中将self.countdown()更改为self.countdown确实会修复错误,但现在函数只是“卡住”了。出现所需的窗口,但没有一个按钮似乎正在工作。

1 个答案:

答案 0 :(得分:1)

command=after()bind()需要不带()的函数名称(有时称为callback

countdown()after()执行,就像任何其他函数一样(但稍后),这意味着:

  1. countdown()会在每次执行中重新创建所有本地值,因此他们不会保留值。您必须使用self.minsself.secs来保留值。

  2. {li>

    countdown()内无法使用

    mins = self.minutes
    secs = self.seconds
    

    因为它会在每次执行中将时间重置为25:00。您必须在start()

    中进行设置

    工作代码

    import tkinter as tk
    
    class Timer:
        def __init__(self, master):
            self.master = master
            master.title("Pomodoro Timer")
    
            self.state = False
            self.minutes = 25
            self.seconds = 0
    
            self.mins = 25
            self.secs = 0
    
            self.display = tk.Label(master, height=10, width=10, textvariable="")
            self.display.config(text="00:00")
            self.display.grid(row=0, column=0, columnspan=2)
    
            self.start_button = tk.Button(master, bg="Green", activebackground="Dark Green", text="Start", width=8, height=4, command=self.start)
            self.start_button.grid(row=1, column=0)
    
            self.pause_button = tk.Button(master, bg="Red", activebackground="Dark Red", text="Pause", width=8, height=4, command=self.pause)
            self.pause_button.grid(row=1, column=1)
    
            self.countdown()
    
        def countdown(self):
            """Displays a clock starting at min:sec to 00:00, ex: 25:00 -> 00:00"""
    
            if self.state == True:
                if self.secs < 10:
                    if self.mins < 10:
                        self.display.config(text="0%d : 0%d" % (self.mins, self.secs))
                    else:
                        self.display.config(text="%d : 0%d" % (self.mins, self.secs))
                else:
                    if self.mins < 10:
                        self.display.config(text="0%d : %d" % (self.mins, self.secs))
                    else:
                        self.display.config(text="%d : %d" % (self.mins, self.secs))
    
                if (self.mins == 0) and (self.secs == 0):
                    self.display.config(text="Done!")
                else:
                    if self.secs == 0:
                        self.mins -= 1
                        self.secs = 59
                    else:
                        self.secs -= 1
    
                    self.master.after(1000, self.countdown)
            else:
                self.master.after(100, self.countdown)
    
        def start(self):
            if self.state == False:
                self.state = True
                self.mins = self.minutes
                self.secs = self.seconds
    
        def pause(self):
            if self.state == True:
                self.state = False
    
    
    
    root = tk.Tk()
    my_timer = Timer(root)
    
    root.mainloop()
    

    编辑:,因为@ EL3PHANTEN指出您可以使用字符串格式来缩短它:

    text='{:02} : {:02}'.format(self.mins,self.secs)
    

    text="%02d : %02d" % (self.mins,self.secs)
    

    我还将self.countdown()行从__init__移到了start(),现在我不需要after()内的第二个countdown()

    我还会在显示self.state = False

    时设置Done!
    import tkinter as tk
    
    class Timer:
        def __init__(self, master):
            self.master = master
            master.title("Pomodoro Timer")
    
            self.state = False
            self.minutes = 25
            self.seconds = 0
    
            self.mins = 25
            self.secs = 0
    
            self.display = tk.Label(master, height=10, width=10, textvariable="")
            self.display.config(text="00:00")
            self.display.grid(row=0, column=0, columnspan=2)
    
            self.start_button = tk.Button(master, bg="Green", activebackground="Dark Green", text="Start", width=8, height=4, command=self.start)
            self.start_button.grid(row=1, column=0)
    
            self.pause_button = tk.Button(master, bg="Red", activebackground="Dark Red", text="Pause", width=8, height=4, command=self.pause)
            self.pause_button.grid(row=1, column=1)
    
        def countdown(self):
            """Displays a clock starting at min:sec to 00:00, ex: 25:00 -> 00:00"""
    
            if self.state == True:
    
                if (self.mins == 0) and (self.secs == 0):
                    self.display.config(text="Done!")
                    self.state = False
                else:
                    self.display.config(text="%02d:%02d" % (self.mins, self.secs))
    
                    if self.secs == 0:
                        self.mins -= 1
                        self.secs = 59
                    else:
                        self.secs -= 1
    
                    self.master.after(1000, self.countdown)
    
        def start(self):
            if self.state == False:
                self.state = True
                self.mins = self.minutes
                self.secs = self.seconds
                self.countdown()
    
        def pause(self):
            if self.state == True:
                self.state = False
    
    
    
    root = tk.Tk()
    my_timer = Timer(root)
    
    root.mainloop()
    "{:02} : {:02}".format(10, 0)