我正在绞尽脑汁试图找出为什么只有在我停止剧本后才出现tkinter窗口。事实证明,如果我的root.after(在我的无限果味循环中)的延迟时间设置为0,则不会出现。将其设置为1或更高会导致它正常工作。这是一个错误还是我错过了关于如何工作的重要事项?我在Mac OS上用Anaconda中的Python 2.7运行它。
import time
import Tkinter as tk
import random
root = tk.Tk()
root.title("random numbers")
root.geometry("220x220+5+5")
frame = tk.Frame(root, width=210, height=210)
frame.pack()
luckynumber = tk.IntVar()
label1 = tk.Label(frame, text="random number").pack(side=tk.LEFT)
display1 = tk.Label(frame, textvariable=luckynumber)
display1.pack( side=tk.LEFT )
def askrandy():
randy = random.randrange(0, 100, 1)
luckynumber.set(randy)
def fruityloop():
time.sleep(.5)
askrandy()
root.after(1, fruityloop)
root.after(0, fruityloop)
root.mainloop()
第二个问题:此代码运行不顺畅。看起来很简单,我认为它会非常稳固。但是我发现它需要几秒钟才能开始并且移动窗口也会导致它口吃。我的主循环作为一个类运行会更好吗?
答案 0 :(得分:0)
这是正常行为。
Tkinter在闲置时维护一个工作队列。这是“空闲”队列。
当您致电after
时,您提供的功能会添加到此队列中。当主事件循环(或对after_idle
的调用)处理队列时,它会根据当前时间和项目运行时间查找应该运行的队列中的项目。在队列处理停止之前运行所有要运行的项目。
如果其中一个将一个项目添加到队列中,其值为零,则它将在其到期时间内运行。如果该项本身将一个项添加到队列中,那么您将从队列中取出一个项并立即放入一个项,以便队列永远不会变空。如果队列永远不会变空,则tkinter无法处理其他类型的事件。
该程序看起来缓慢而生涩的原因是由于对sleep
的调用。当你打电话给sleep
时,tkinter会这样做:它会睡觉。它无法处理任何事件,甚至只是刷新窗口的事件。如果你希望每半秒调用askrandy
一次,你应该简单地用值{500调用after
,而不是用零值调用它然后再睡半秒钟。
主窗口是否是一个类不会影响你的程序。您只需停止使用sleep
,并为after
提供合理的值。如果您尝试显示一个简单的动画,则值30就足够小了。
答案 1 :(得分:-1)
这是没有sleep()
的情况。但我不知道它是否可以提供帮助。它在Linux上运行得很快。
如果您在IDLE
中运行代码,那么您可能会遇到问题,因为它使用Tkinter
来显示窗口并运行自己的mainloop()
,但Tkinter
应该只运行一个mainloop()
}}。您可以直接在控制台python script.py
中尝试。
import Tkinter as tk
import random
# --- functions ---
def fruityloop():
randy = random.randrange(0, 100, 1)
luckynumber.set(randy)
# run again after 500ms = 0.5s
root.after(500, fruityloop)
# --- main ---
root = tk.Tk()
root.title("random numbers")
root.geometry("220x220+5+5")
luckynumber = tk.IntVar()
frame = tk.Frame(root, width=210, height=210)
frame.pack()
label = tk.Label(frame, text="random number")
label.pack(side=tk.LEFT)
display = tk.Label(frame, textvariable=luckynumber)
display.pack(side=tk.LEFT)
# run first time
fruityloop()
root.mainloop()