2014-07-09 80 views
0

當我設置root.after_idle()時,它停止了Toplevel的運行。Tkinter after_idle殺死頂層

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未運行。一旦等於> 500000(根據您的機器速度調整),所有工作都按預期開始。我閱讀文檔的方式,after_idle只能在沒有其他事情的情況下運行。在這種情況下,它似乎阻止了Toplevel的處理。

在現實生活中,idletask是一個相當大的狀態機,它正在讀取和寫入加工中心的數據。我知道有人會建議我使用root.after()。我是,爲了其他目的。這個代碼是證明問題的最不重要的部分。這完美的工作,直到Toplevel被稱爲我想要的。你會注意到空閒任務仍然在運行,因爲它最終達到500000並停止。

將idletask移動到單獨的線程是可能的,但在這一點上非常不理想。

回答

1

這是使用after_idle的錯誤方法。至少你需要在兩次調用之間給一毫秒。否則事件循環從來沒有機會處理任何其他事件。會發生的是,在第一次檢查空閒之後,它會查看空閒回調列表。如果有什麼東西,它會調用它。然後,它會繼續尋找,直到回調列表爲空。只有這樣它纔會返回到處理正常事件。

但是,由於您不斷向事情列表中添加一些內容,因此閒置進程正在有效追逐它自己的尾部。它會關閉一個項目並執行該項目,這會推動隊列中的某些內容。然後它將該項目關閉並執行,將其推送到隊列中,依此類推。實際上,當它閒置時,它應該做的事情無限清單,它會在放棄控制權之前嘗試完成所有事情。

+0

好的,我完全理解。它確實給我另外兩個問題。爲什麼根窗口上的小部件繼續工作?更重要的是,我是否理解after_idle只會在通過mainloop()時沒有別的任何操作時才被調用。 – Burtski