【问题标题】:Why does time.sleep pause tkinter window before it opens为什么 time.sleep 在打开之前暂停 tkinter 窗口
【发布时间】:2015-07-28 20:09:45
【问题描述】:

我正在为体育场开发一个程序,time.sleep() 在窗口打开之前暂停程序,而不是在我想要的时候暂停。这种行为的解释是什么?

import Tkinter as tk
import time
import random
root = tk.Tk()

label = tk.Label(root, text="Navigating To Seat")
label.pack(pady=10, padx=10)

rand = random.randint(6, 16)

while rand != 0:
    label2 = tk.Label(root, text="Foward:  " + str(rand) + "m")
    label2.pack()
    rand = rand - 1
    time.sleep(1)
    label2.pack_forget()

root.mainloop()

【问题讨论】:

  • 您是否尝试将问题的标题放入 Google 搜索中?
  • 什么不会暂停程序?这正是sleep 的用途。如果您不希望它这样做,为什么要调用它?

标签: python python-2.7 tkinter


【解决方案1】:

time.sleep 所做的是暂停程序的执行。如果您这样做 6-16 次,每次 1 秒,然后再调用 mainloop(),您要求它在启动 GUI 之前等待 6-16 秒。

您可能不了解事件循环编程的工作原理。阅读一些 Tkinter 教程应该可以很好地理解这个想法。如果你想要一个不太关注 Tkinter 的解释,以及更多关于正在发生的事情的细节以及解决它的不同方法的信息,请参阅Why your GUI app freezes

无论如何,我想我可以猜到你想要做什么,即使你的问题并不清楚:你想启动 GUI,然后每秒替换 Label。为此,您必须在 GUI 运行时等待,而不是在它启动之前等待。

但您也不能只在 GUI 运行时调用 sleep。当您的程序处于睡眠状态时,GUI 无法运行(同样,这就是 sleep 的意思)。

解决这个问题的最简单方法是将循环转换为一系列函数调用,每个函数调用都会安排下一个函数在一秒钟后运行,使用 after 方法。例如:

import Tkinter as tk
import random
root = tk.Tk()

label = tk.Label(root, text="Navigating To Seat")
label.pack(pady=10, padx=10)

rand = random.randint(6, 16)
label2 = None

def add_label():
    global rand
    global label2
    if not rand:
        root.quit()
    if label2:
        label2.pack_forget()
    label2 = tk.Label(root, text="Foward:  " + str(rand) + "m")
    label2.pack()
    rand = rand - 1
    root.after(1000, add_label)

add_label()
root.mainloop()

当您第一次调用add_label() 时,它会创建初始标签,要求Tkinter 在1000 毫秒内再次调用add_label(),然后返回。因此,在您开始循环后一秒钟,它会再次被调用,这会创建下一个标签并要求Tkinter 在一秒钟后再次调用它。这一直持续到您将rand 一直递减到0,此时您调用quit 而不是after,这会结束主循环,从而结束程序。

关于此程序,您可能还需要解决其他一些问题。例如,您无需每次都销毁和创建一个新的 Widget 标签,而只需更改其文本,或者更简单,将 rand 与标签连接到 IntVar,这样只需更新 rand 就会自动更改文本。此外,对于比这个程序更简单的东西,您可能希望用更干净的东西替换全局变量——大多数 Tkinter 教程通过大约第二个或第三个示例向您展示如何使用 Frame 子类,这给您一个方便用于组织小部件和成员变量的地方,例如 rand

【讨论】:

  • 这是一个很好的解释,但如果你提到方法after_cancel...
  • @Xenomorph:你会在哪里使用after_cancel 这个设计? after 方法不会重复触发,只会触发一次,所以这里没有什么可以取消的。
  • 只是提到它与after方法相比,我没有说解决方案需要它..也许我只是疯了。
  • @Xenomorph:我认为它在这里并不重要,并且在我链接到的after 文档中已经提到过(以及无论如何都是下一节)。你能想出一种方法来提供解释,让 OP 知道它有什么用处,而无需提出更复杂的示例(例如,添加“停止”按钮)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 2017-01-17
  • 1970-01-01
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多