2012-03-19 64 views
6

我遇到了阻止'feed'的問題;取消參數似乎對after方法沒有任何影響。儘管「饋送停止」被打印到控制檯。如何在功能後停止tkinter?

我試圖有一個按鈕,將開始飼料和另一個將停止飼料。

from Tkinter import Tk, Button 
import random 

    def goodbye_world(): 
     print "Stopping Feed" 
     button.configure(text = "Start Feed", command=hello_world) 
     print_sleep(True) 

    def hello_world(): 
     print "Starting Feed" 
     button.configure(text = "Stop Feed", command=goodbye_world) 
     print_sleep() 

    def print_sleep(cancel=False): 
     if cancel==False: 
      foo = random.randint(4000,7500) 
      print "Sleeping", foo 
      root.after(foo,print_sleep) 
     else: 
      print "Feed Stopped" 


    root = Tk() 
    button = Button(root, text="Start Feed", command=hello_world) 

    button.pack() 


    root.mainloop() 

隨着輸出:

Starting Feed 
Sleeping 4195 
Sleeping 4634 
Sleeping 6591 
Sleeping 7074 
Stopping Feed 
Sleeping 4908 
Feed Stopped 
Sleeping 6892 
Sleeping 5605 
+0

我不完全確定tkinter是如何工作的,但這看起來像是一個線程問題。如果您取消全局(線程安全),那麼這是否可以解決問題? – mklauber 2012-03-19 19:46:12

+0

@mklauber:不,不是線程問題。 Tkinter是單線程的。 – 2012-03-19 20:31:40

+0

@BryanOakley:謝謝。這就是我作爲評論發佈的原因。我不確定,所以我只是想提出這個問題。 – mklauber 2012-03-19 20:33:04

回答

13

的問題是,即使你打電話print_sleepTrue停止循環,不過已經有了暫掛作業等待開火。按下停止按鈕不會導致新的作業啓動,但舊作業仍然存在,並且當它自己調用時,它會通過False導致循環繼續。

您需要取消掛起的作業,以便它不運行。例如:

def cancel(): 
    if self._job is not None: 
     root.after_cancel(self._job) 
     self._job = None 

def goodbye_world(): 
    print "Stopping Feed" 
    cancel() 
    button.configure(text = "Start Feed", command=hello_world) 

def hello_world(): 
    print "Starting Feed" 
    button.configure(text = "Stop Feed", command=goodbye_world) 
    print_sleep() 

def print_sleep(): 
    foo = random.randint(4000,7500) 
    print "Sleeping", foo 
    self._job = root.after(foo,print_sleep) 

注意:確保你初始化self._job的地方,比如在你的應用程序對象的構造函數。

13

當你調用root.after(...),它會返回一個標識符。您應該跟蹤該標識符(例如,將其存儲在實例變量中),然後您可以稍後致電root.after_cancel(after_id)來取消它。