python time.sleep() 延迟之前的命令
python time.sleep() delays previous commands
当试图中断一个 tkinter 应用程序时,time.sleep() 似乎搁置了一些先前的命令。根据我的理解和以前的经验,label1的text应该设置成"before"一秒,然后改成"after"。但是,"before" 值永远不会出现,"after" 在执行后一秒正常打印。
from tkinter import *
import time
class Display(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label1 = Label(text = "before")
label1.grid()
self.after(1000, label1.config(text = "after"))
def main():
root = Tk()
Display(root)
root.mainloop()
if __name__ == '__main__':
main()
请注意,使用 time.sleep(...) 产生与 tkinter after(...)
相同的结果
from tkinter import *
import time
class Display(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label1 = Label(text = "before")
label1.grid()
time.sleep(1)
label1.config(text = "after")
def main():
root = Tk()
Display(root)
root.mainloop()
if __name__ == '__main__':
main()
我想 tkinter 正在等待执行图形工作的东西(控制台没有问题)但我没有看到什么并且 tkinter 文档没有解决这个问题。
有没有一种简单的方法可以得到明显的预期结果?
没用也就不足为奇了。想一想 Tk 框架在做什么:它正在创建您的 windows、display = Display()
,然后线程停止。对象未完全创建。您是否希望 Tk 渲染一个通过其构造函数进行到一半的对象?
首先,尝试将所有与线程相关的代码移出构造函数。应该允许构造函数正常完成,线程代码应该在另一个函数中。
其次,在正常逻辑中间使用 thread.sleep 是不好的做法。通常,您启动一个单独的线程,该线程可以根据需要等待和休眠。 (虽然不知道Tk有没有特殊的处理方式。)
time.sleep(...)
给出的结果与 after(...)
调用的结果不同。
time.sleep
方法 运行s,但在第二个过去之前没有显示任何内容。您可以通过在睡眠呼叫之前放置 print('before')
来查看。您会看到打印语句在创建 window 前一秒执行。这是因为 Tkinter 在睡眠期间没有更新任何东西。所以在睡眠结束之前什么都不会发生,之后标签会立即更新。此外,在睡眠结束之前不会调用主循环,因此 Tkinter 还不在其主循环中。您可以在睡眠呼叫之前使用 self.parent.update()
强制 Tkinter 进行更新。您将看到 window 显示,标签为 'before'
,等待一秒钟,标签变为 'after'
。然而,在这一秒内 window 没有响应,这就是为什么将睡眠与 Tkinter 一起使用是一个坏主意。
after 几乎总是更好的选择,因为它 return 立即执行,因此它不会阻止进一步的执行,并安排指定的函数在指定的时间后执行,而不是睡眠。但是,after 期望传递一个函数名,但是你传递了一个函数调用。这意味着在评估 after 调用时,函数是 运行 并且 return 值(即 None
)作为函数名称传递。因此,您会看到标签在 window 打开时发生了更改,因为更改是在评估后调用时进行的。您应该做的是将函数名称传递给 after:
def update_label:
label1.config(text = "after")
self.after(1000, update_label)
或更短,通过创建一个匿名函数:
self.after(1000, lambda: label1.config(text = "after"))
这会给你显示带有 'before'
的标签的预期结果,它会在一秒钟后变为 'after'
,而不会阻塞 Tkinter 的主循环。
当试图中断一个 tkinter 应用程序时,time.sleep() 似乎搁置了一些先前的命令。根据我的理解和以前的经验,label1的text应该设置成"before"一秒,然后改成"after"。但是,"before" 值永远不会出现,"after" 在执行后一秒正常打印。
from tkinter import *
import time
class Display(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label1 = Label(text = "before")
label1.grid()
self.after(1000, label1.config(text = "after"))
def main():
root = Tk()
Display(root)
root.mainloop()
if __name__ == '__main__':
main()
请注意,使用 time.sleep(...) 产生与 tkinter after(...)
相同的结果from tkinter import *
import time
class Display(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label1 = Label(text = "before")
label1.grid()
time.sleep(1)
label1.config(text = "after")
def main():
root = Tk()
Display(root)
root.mainloop()
if __name__ == '__main__':
main()
我想 tkinter 正在等待执行图形工作的东西(控制台没有问题)但我没有看到什么并且 tkinter 文档没有解决这个问题。
有没有一种简单的方法可以得到明显的预期结果?
没用也就不足为奇了。想一想 Tk 框架在做什么:它正在创建您的 windows、display = Display()
,然后线程停止。对象未完全创建。您是否希望 Tk 渲染一个通过其构造函数进行到一半的对象?
首先,尝试将所有与线程相关的代码移出构造函数。应该允许构造函数正常完成,线程代码应该在另一个函数中。
其次,在正常逻辑中间使用 thread.sleep 是不好的做法。通常,您启动一个单独的线程,该线程可以根据需要等待和休眠。 (虽然不知道Tk有没有特殊的处理方式。)
time.sleep(...)
给出的结果与 after(...)
调用的结果不同。
time.sleep
方法 运行s,但在第二个过去之前没有显示任何内容。您可以通过在睡眠呼叫之前放置 print('before')
来查看。您会看到打印语句在创建 window 前一秒执行。这是因为 Tkinter 在睡眠期间没有更新任何东西。所以在睡眠结束之前什么都不会发生,之后标签会立即更新。此外,在睡眠结束之前不会调用主循环,因此 Tkinter 还不在其主循环中。您可以在睡眠呼叫之前使用 self.parent.update()
强制 Tkinter 进行更新。您将看到 window 显示,标签为 'before'
,等待一秒钟,标签变为 'after'
。然而,在这一秒内 window 没有响应,这就是为什么将睡眠与 Tkinter 一起使用是一个坏主意。
after 几乎总是更好的选择,因为它 return 立即执行,因此它不会阻止进一步的执行,并安排指定的函数在指定的时间后执行,而不是睡眠。但是,after 期望传递一个函数名,但是你传递了一个函数调用。这意味着在评估 after 调用时,函数是 运行 并且 return 值(即 None
)作为函数名称传递。因此,您会看到标签在 window 打开时发生了更改,因为更改是在评估后调用时进行的。您应该做的是将函数名称传递给 after:
def update_label:
label1.config(text = "after")
self.after(1000, update_label)
或更短,通过创建一个匿名函数:
self.after(1000, lambda: label1.config(text = "after"))
这会给你显示带有 'before'
的标签的预期结果,它会在一秒钟后变为 'after'
,而不会阻塞 Tkinter 的主循环。