Tkinter solo llama after_idle una vez

Soy nuevo en Tkinter, así que me disculpo si esto es fácil, pero he buscado durante un par de horas y no puedo resolverlo. Lo que quiero hacer es que después de que mainloop esté inactivo, siempre quiero llamar a la función checkForGroupUpdates (). Cuando ejecuto el siguiente código, solo se ejecuta una vez. No puedo imaginar que se ejecute cada vez que el mainloop esté inactivo. Aprecio la ayuda.

from Tkinter import * import random class Network(Frame): """ Implements a stop watch frame widget. """ def __init__(self, parent=None, **kw): Frame.__init__(self, parent, kw) self.makeWidgets() def makeWidgets(self): """ Make the time label. """ self._canvas = Canvas(self, width=600, height=400) self._canvas.pack() def checkForGroupUpdates(self): print "checking" h=0 this=10 while this>.0001: this=random.random() print h h=h+1 print "checked" def main(): root = Tk() nw = Network(root) nw.pack(side=TOP) root.after_idle(nw.checkForGroupUpdates) root.mainloop() if __name__ == '__main__': main() 

En lugar de llamar a la función todo el tiempo cuando la aplicación está inactiva, solo debe llamarla una vez cada fracción de segundo. Por ejemplo, si desea verificar 10 veces por segundo, haría algo como esto:

 def checkForGroupUpdates(self):  self.after(100, self.checkForGroupUpdates) 

Una vez que llame a esa función una vez, se ordenará que se vuelva a llamar en 100 ms. Esto continuará hasta que el progtwig salga. Si el progtwig pasa a “no inactivo” (es decir, mientras responde a un clic del botón), esta función se detendrá ya que tkinter es de un solo hilo. Una vez que el progtwig vuelva a estar inactivo, la verificación continuará.

@ user1763510, note que en la respuesta de Bryan Oakley, él tiene checkForGroupUpdates llama self.after nuevamente. Esto se debe a que self.after solo hace una sola llamada, por lo que obtener llamadas repetidas requiere que se llame a sí mismo dentro de la función que recibe la primera llamada. De esta manera, se sigue llamando repetidamente.

Lo mismo ocurre con la función after_idle() . checkForGroupUpdates tener checkForGroupUpdates call after_idle() nuevamente en la parte inferior.

Aquí está la documentación para after , after_idle , etc. Incluso hay un pequeño ejemplo en la descripción after , que lo aclara todo.

Documentación: http://effbot.org/tkinterbook/widget.htm

Ejemplo del enlace de arriba, bajo la descripción after :

 #Method 1 class App: def __init__(self, master): self.master = master self.poll() # start polling def poll(self): ... do something ... self.master.after(100, self.poll) 

Para usar after_idle en after_idle lugar, se vería así:

 #Method 2 class App: def __init__(self, master): self.master = master self.poll() # start polling def poll(self): ... do something ... self.master.update_idletasks() self.master.after_idle(self.poll) 

Observe la adición de la línea self.master.update_idletasks() . Esto dibuja la GUI y maneja pulsaciones de botones y cosas. De lo contrario, after_idle() absorberá todos los recursos y no permitirá que la GUI se actualice correctamente en mainloop() .

Una alternativa al uso.

  self.master.update_idletasks() self.master.after_idle(self.poll) 

es usar:

  #Method 3 self.master.update_idletasks() self.master.after(0, self.poll) 

Usar self.master.after(0, self.poll) es mi técnica preferida, ya que me permite cambiar fácilmente el 0 a otra cosa si decido que no necesito ejecutar self.poll constantemente. Al boost el tiempo de retardo a al menos 1 ms, ya no necesita llamar a self.master.update_idletasks() en absoluto. Entonces, esto funciona también:

  #Method 4 self.master.after(1, self.poll) 

También note que para todos los ejemplos anteriores, llamar a self.poll() en la función __init__ es lo que lo pone todo en marcha, y almacenar master en self.master es simplemente necesario para que dentro de la poll pueda llamar la función after o after_idle través de self.master.after_idle , por ejemplo.

P: ¿Es estable / funciona?
R: Ejecuté un código de prueba utilizando el Método 3 justo por encima de ~ 21 horas, y se ejecutó de manera estable todo el tiempo, permitiendo que la GUI fuera utilizable y todo.

P: ¿Cuál es la comparación de velocidad para cada método anterior?
UNA:

  • Método 1: (No lo puse a prueba de velocidad)
  • Método 2: ~ 0.44 ms / iteración
  • Método 3: ~ 0.44 ms / iteración
  • Método 4: ~ 1.61 ms / iteración

P: ¿Cuál es mi método preferido?
A: Método 3 o 4.