2012-03-19 23 views
6

Tengo un problema al detener el 'feed'; el argumento cancelar no parece tener ningún impacto en el método posterior. Aunque "alimentación detenida" se imprime en la consola.¿Cómo detengo tkinter después de la función?

Estoy intentando tener un botón que iniciará la alimentación y otro que detendrá la alimentación.

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 la salida:

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

No estoy del todo seguro sobre cómo funciona tkinter, pero esto se parece bastante a un problema de enhebrado para mí. Si haces que cancelar un (hilo seguro) global, ¿resuelve el problema? – mklauber

+0

@mklauber: no, no es un problema de enhebrado. Tkinter tiene un solo subproceso. –

+0

@BryanOakley: Gracias. Es por eso que publiqué como comentario. No estaba seguro así que solo quería plantear la pregunta. – mklauber

Respuesta

13

El problema es que, aunque está llamando al print_sleep con True para detener el ciclo, ya hay un trabajo pendiente esperando para iniciarse. Al presionar el botón de detención no se activará un nuevo trabajo, pero el anterior aún está allí, y cuando se llama a sí mismo, pasa a False lo que hace que el ciclo continúe.

Debe cancelar el trabajo pendiente para que no se ejecute. Por ejemplo:

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: asegúrese de inicializar self._job algún lugar, como en el constructor de su objeto de aplicación.

13

Cuando se llama a root.after(...), devolverá un identificador. Debe realizar un seguimiento de ese identificador (por ejemplo, almacenarlo en una variable de instancia), y luego puede llamar al root.after_cancel(after_id) para cancelarlo.

Cuestiones relacionadas