简体   繁体   English

如何在按下按钮之前不断更新 tkinter 标签?

[英]How do I update a tkinter label continually until a button is pressed?

I'm attempting to create a simple timer application in which the user presses a start button (or uses the keybind) and the clock continually updates until the user presses a stop button (or uses the keybind), but in trying to create this I have got stuck in an infinite loop.我正在尝试创建一个简单的计时器应用程序,其中用户按下开始按钮(或使用键绑定)并且时钟不断更新,直到用户按下停止按钮(或使用键绑定),但在尝试创建此我陷入了无限循环。

I've tried creating a boolean flag in which True indicates to end the updating and used a while loop to check this, however the program ends up stuck in an infinite loop.我尝试创建一个布尔标志,其中 True 表示结束更新并使用 while 循环来检查这一点,但是程序最终陷入了无限循环。 This is all in python 3.x (specifically v3.6.7).这一切都在python 3.x(特别是v3.6.7)中。 In the code provided, I reduced it as far as I could whilst maintaining the error and context of the error.在提供的代码中,我尽可能地减少它,同时保持错误和错误的上下文。 I also removed the keybinds I mentioned earlier as these are not part of the issue.我还删除了我之前提到的键绑定,因为它们不是问题的一部分。

import tkinter as tk
class cubeTimer():
    def __init__(self):
        ##Defines parts of timer
        self.start_time = 0.0
        self.end_time = 0.0
        self.difference = 0.0
    def get_time(self,num):
        ##Gets time since epoch
        if num == 1:
            self.start_time = time.time()
        elif num == 2:
            self.end_time = time.time()
    def get_difference(self):
        ##Finds difference bwteen start and end times
        self.difference = self.end_time - self.start_time
        return self.difference
class cubeGUI():
    def __init__(self):
        ##Instance variables for later use
        self.num = 0
        self.time_difference = 0
        self.flag = False
        ##Creates instance of timer class
        self.timer = cubeTimer()
        ##Creates GUI
        self.root = tk.Tk()
        ##Label to show the solve time
        self.time_label = tk.Label(text='-',height=5,width=10)
        self.time_label.grid(row=1,columnspan=2,sticky=tk.W)
        ##Button to start timer
        self.start_button = tk.Button(text='Start',height=5,width=10,command=self.start_process)
        self.start_button.grid(row=2,column=0)
        ##Button to end timer, initialised as disabled
        self.end_button = tk.Button(text='End',state=tk.DISABLED,height=5,width=10,command=self.end_process)
        self.end_button.grid(row=2,column=1)
    def start_process(self):
        ##Sets variable
        self.num = 1
        ##Calls timer to get time
        self.timer.get_time(self.num)
        ##Configures necessary buttons
        self.start_button.configure(state=tk.DISABLED)
        self.end_button.configure(state=tk.NORMAL)
        while self.flag == False:
            self.time_difference = self.timer.get_difference()
            self.time_label.configure(text=self.time_difference)
            time.sleep(0.1)
    def end_process(self):
        ##Sets variable
        self.num = 2
        ##Calls timer to get time
        self.timer.get_time(self.num)
        ##Updates flag
        self.flag = True
        ##Configures necessary button
        self.end_button.configure(state=tk.DISABLED)
        ##Calls time difference
        self.time_difference = self.timer.get_difference()
        ##Puts it on screen
        self.time_label.configure(text=self.time_difference)
myTimer = cubeGUI()

I expected the program to update the time label every 0.1 seconds (or any given time period), but instead the program freezes as it encounters an infinite loop and becomes stuck.我希望程序每 0.1 秒(或任何给定的时间段)更新时间标签,但程序在遇到无限循环时会冻结并卡住。

You can't use a loop inside a GUI because it interferes with the GUI mainloop.您不能在 GUI 内使用循环,因为它会干扰 GUI 主循环。 Instead you have to structure your program to integrate into the mainloop.相反,您必须构建您的程序以集成到主循环中。 In tkinter, that's done with the after() method.在 tkinter 中,这是通过after()方法完成的。 Here is your code fixed (as far as I can infer what you are trying to do), including a proper class:这是您的代码已修复(据我所知,您正在尝试做什么),包括一个适当的类:

import tkinter as tk

class CubeTimer(tk.Frame):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)

        self.timer = ' '
        self.time_value = tk.IntVar()

        ##Label to show the solve time
        time_label = tk.Label(self, textvariable=self.time_value,height=5,width=10)
        time_label.grid(row=1,columnspan=2,sticky=tk.W)
        ##Button to start timer
        self.start_button = tk.Button(self, text='Start',height=5,width=10,command=self.start_process)
        self.start_button.grid(row=2,column=0)
        ##Button to end timer, initialised as disabled
        self.end_button = tk.Button(self, text='End',state=tk.DISABLED,height=5,width=10,command=self.end_process)
        self.end_button.grid(row=2,column=1)

    def timer_tick(self):
        self.time_value.set(self.time_value.get() + 1)
        self.timer = self.after(1000, self.timer_tick) # schedule this method to be called again in 1,000 millisconds (1 second)

    def start_process(self):
        ##Configures necessary buttons
        self.start_button.configure(state=tk.DISABLED)
        self.end_button.configure(state=tk.NORMAL)
        self.timer_tick()

    def end_process(self):
        self.after_cancel(self.timer) # cancel the scheduled method call

        ##Configures necessary button
        self.end_button.configure(state=tk.DISABLED)
        self.start_button.configure(state=tk.NORMAL)

def main():
    root = tk.Tk()
    myTimer = CubeTimer(root)
    myTimer.pack()
    root.mainloop()

if __name__ == "__main__":
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM