Tkinter after_idle杀死了顶级

时间:2014-07-09 14:18:01

标签: tkinter

当我设置root.after_idle()时,它会阻止Toplevel运行。

from Tkinter import *
blah=1

def afterloop():
    label.config(text=str(blah))
    root.after(500,afterloop)

def idleloop():
    global blah
    blah=blah+1
    if blah<500000:
        root.after_idle(idleloop)

def second():
    spam=Toplevel()
    button2=Button(spam,text="Button 2",command=spam.destroy)
    button2.pack()

root=Tk()
button1=Button(root,text="Press to Open",command=second)
button1.pack()
label=Label(root,text="*********************")
label.pack()
root.update()
root.after_idle(idleloop)
root.after(500,afterloop)
root.mainloop()

当after_idle处于活动状态时,Toplevel不会运行。一旦blah> 500000(调整机器速度),所有开始按预期工作。我阅读文档的方式,after_idle应该只在没有其他事情要做的情况下运行。在这种情况下,它似乎阻止了Toplevel的处理。

在现实生活中,idletask是一个相当大的状态机,它正在从加工中心读取和写入数据。我知道有人会建议我使用root.after()。我是,出于其他目的。此代码只是证明问题的最小代码。在调用Toplevel之前,这非常适合我想要的东西。您将注意到空闲任务仍在运行,因为它最终达到500000并停止。

将idletask移动到一个单独的线程是可能的,但此时非常不受欢迎。

1 个答案:

答案 0 :(得分:1)

这是使用after_idle的错误方法。至少你需要在调用它之间给出一毫秒。否则,事件循环永远不会有机会处理任何其他事件。发生的事情是,在第一次检查空闲后,它会查看空闲回调列表。如果那里有什么东西,就会调用它。然后,它会查找更多内容,并继续执行,直到回调列表为空。只有这样才能恢复处理正常事件。

但是,由于你不断在要做的事情列表中添加一些内容,因此空闲进程实际上正在追逐它自己的尾巴。它拉出一个项目并执行它,这会推动队列中的某些内容。然后它将该项目拉出并执行,将其推送到队列中,依此类推。当它变得空闲时,你有效地拥有它应该做的无限列表,它会在放弃控制之前尝试完成所有这些事情。