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。