2012-03-19 12 views
6

Ho riscontrato un problema durante l'interruzione del "feed"; l'argomento cancel non sembra avere alcun impatto sul metodo after. Anche se "Feed stopped" viene stampato sulla console.Come posso interrompere tkinter dopo la funzione?

Sto tentando di avere un pulsante che avvierà il feed e un altro che interromperà il feed.

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

Con l'uscita:

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

Non sono completamente sicuro di come funziona tkinter, ma mi sembra piuttosto un problema di threading. Se si effettua una cancellazione globale (thread safe), questo risolve il problema? – mklauber

+0

@mklauber: no, non è un problema di threading. Tkinter è single-threaded. –

+0

@BryanOakley: Grazie. Questo è il motivo per cui ho postato un commento. Non ero sicuro quindi volevo solo sollevare la domanda. – mklauber

risposta

13

Il problema è che, anche se stai chiamando print_sleep con True per interrompere il ciclo, c'è già un lavoro in sospeso in attesa di sparare. Premendo il pulsante stop non si attiva un nuovo lavoro, ma il vecchio lavoro è ancora lì, e quando si chiama da solo, passa in False che fa continuare il ciclo.

È necessario annullare il processo in sospeso in modo che non venga eseguito. Per esempio:

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) 

Nota: assicurarsi di inizializzare self._job da qualche parte, come ad esempio nel costruttore del vostro oggetto dell'applicazione.

13

Quando si chiama root.after(...), verrà restituito un identificatore. È necessario tenere traccia di tale identificatore (ad es. Memorizzarlo in una variabile di istanza) e successivamente è possibile chiamare lo root.after_cancel(after_id) per annullarlo.

Problemi correlati