为什么time.sleep在打开之前暂停tkinter窗口 - python

我正在为体育场开发程序,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()

python大神给出的解决方案

time.sleep的作用是暂停程序的执行。如果您执行6-16次操作(每次1秒),然后再调用mainloop(),则要求它等待6-16秒才能启动GUI。

您可能不了解事件循环编程的工作原理。通读一些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)的地方。