tkinter窗口不显示 - 如果.event时间在循环内是0

时间:2017-01-09 05:05:26

标签: python tkinter

我正在绞尽脑汁试图找出为什么只有在我停止剧本后才出现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()

第二个问题:此代码运行不顺畅。看起来很简单,我认为它会非常稳固。但是我发现它需要几秒钟才能开始并且移动窗口也会导致它口吃。我的主循环作为一个类运行会更好吗?

2 个答案:

答案 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()