Tkinter 网格和 time.sleep()

Tkinter grid and time.sleep()

我希望标签是 .grid(),然后程序等待 3 秒,然后是 .grid_forget()。在执行 .grid 时我很困惑。例如:

def remove_choice(self):
    while True:
        try:
            get = int(self.entry_remove_choice.get())
        except ValueError:
            self.label_error_remove.grid(row=10,column=6) #A
            time.sleep(3)
            self.label_error_remove.grid_forget() #B
            #Empty entry box
            break
        else:
            #continue code
            break

按下按钮后执行remove_choice,按钮显示按下三秒,然后#A和#B一次性执行,无任何显示。

如果删除#B,则错误消息会在三秒后显示。

如果交换 #A 和 #B 以打印到终端,那么程序将按照您的想法运行,一条消息等待三秒钟,然后是另一条消息。

如果你做了一个非常草率的解决方案(对于这个程序我并不介意)并且这样做:

def remove_choice(self):
    while True:
        try:
            get = int(self.entry_remove_choice.get())
        except ValueError:
            self.label_error_remove.grid(row=10,column=6) #A
            for n in range (1,1000):
                print("abc")
            self.label_error_remove.grid_forget()
            break
        else:
            #continue code
            break

执行时 "abc" 打印 1000 次大约需要 1.5 秒,然后程序显示网格。

任何关于如何让 TKinter 等待的建议。

也有人可以解释为什么网格是这样工作的,谢谢。

与其每次都尝试 'forgetting' 标签,不如清除错误消息文本?

我下面的示例将等待用户按下按钮并显示错误消息 3 秒。我正在使用 .after 方法在显示错误消息后 3 秒(3000 毫秒)安排 hideError 方法。

try:
    import tkinter as tk
except:
    import Tkinter as tk

import time

class App(tk.Frame):
    def __init__(self,master=None,**kw):
        tk.Frame.__init__(self,master=master,**kw)
        self.errorMessage = tk.StringVar()
        self.ErrorLabel = tk.Label(textvar=self.errorMessage)
        self.ErrorLabel.grid()
        self.button = tk.Button(text="Press Me",command=self.showError)
        self.button.grid()


    def showError(self):
        # Disable the button and show the error message
        self.button['state'] = tk.DISABLED
        self.errorMessage.set("Error Message!!!!")
        self.after(3000,self.hideError)
    def hideError(self):
        #Enable the button and clear the error message.
        self.button['state'] = tk.NORMAL
        self.errorMessage.set("")

if __name__ == '__main__':
    root = tk.Tk()
    App(root).grid()
    root.mainloop()

在 GUI 应用程序中使用 while True 循环或 time.sleep 被认为是不好的做法。它们会阻止 GUI 更新,因此在您的代码中这两个操作似乎同时发生,因为 time.sleep 操作会阻止 GUI 并阻止重绘屏幕。

编辑:从回调传递参数。

当前的问题是 after 方法需要接收对函数的引用。 self.hideError(3) returns NoneType 未引用函数调用。我们可以使用匿名函数和 lambda 来解决这个问题。 我已经开始使用这段代码来提供帮助,它来自 guizero

def with_args( func_name, *args):
    """Helper function to make lambda functions easier
    Thanks to guizero"""
    return lambda: func_name(*args)

然后在您的主要代码部分中,该行将如下所示。

self.after(3000,with_args(self.hideError,3))

编辑:还有一种更简单的方法。 .after 方法本身可以接受参数。

self.after(3000,self.hideError,3)