python - mainloop - toplevel tkinter
La secuencia de comandos de Tkinter se bloquea al crear el segundo widget de Toplevel (3)
Tengo un script de Python que usa Tkinter para la GUI. Mi pequeño script debería crear un widget Toplevel cada X segundos. Cuando ejecuto mi código, el primer widget Toplevel se crea con éxito, pero cuando intenta crear uno, el programa se bloquea.
Lo que estoy haciendo es usar el método after para llamar a la función startCounting cada 5 segundos junto con el mainloop de root. Cada vez que se llama a esta función, anexo un objeto del widget Toplevel a una lista y comienzo un nuevo hilo que, con suerte, ejecutará el nuevo mainloop.
Estaría muy agradecido si alguien pudiera resolver este problema. Por cierto, este es solo un pequeño guión que estoy usando actualmente para resolver mi problema, lo que me impide continuar con mi proyecto de escuela real.
El código:
import threading,thread
from Tkinter import *
def startCounting():
global root
global topLevelList
global classInstance
topLevelList.append (Toplevel())
topLevelList[len(topLevelList)-1].title("Child")
classInstance.append(mainLoopThread(topLevelList[len(topLevelList)-1]))
root.after(5000,startCounting)
class mainLoopThread(threading.Thread):
def __init__(self,toplevelW):
self.toplevelW = toplevelW
threading.Thread.__init__(self)
self.start()
def run(self):
self.toplevelW.mainloop()
global classInstance
classInstance = []
global topLevelList
topLevelList = []
global root
root = Tk()
root.title("Main")
startCounting()
root.mainloop()
¿Hay alguna razón por la que desee (o crea que necesita) un bucle de evento por ventana de nivel superior? Un bucle de evento único es capaz de manejar docenas (si no cientos o miles) de ventanas de nivel superior. Y, como se ha señalado en otra respuesta, no puede ejecutar este bucle de evento en un hilo separado.
Por lo tanto, para corregir su código, solo necesita usar un único bucle de evento y ejecutarlo en el hilo principal.
Tkinter está diseñado para ejecutarse solo desde el hilo principal. Ver los documentos :
Simplemente ejecute todo el código de UI en el hilo principal, y permita que los escritores escriban en un objeto Queue; p.ej
... y sigue un ejemplo sustancial, que muestra hilos secundarios que escriben solicitudes a una cola, y el bucle principal es el único responsable de todas las interacciones directas con Tk.
A muchos objetos y subsistemas no les gusta recibir solicitudes de varios hilos múltiples, y en el caso del kit de herramientas GUI no es raro que se necesite específicamente usar solo el hilo principal .
La arquitectura de Python correcta para este problema siempre es dedicar un hilo (el principal, si se debe) a servir al objeto o subsistema meticuloso; cualquier otro hilo que requiera interacción con dicho subsistema u objeto debe obtenerlo haciendo cola en las solicitudes al hilo dedicado (y posiblemente esperando en una "cola de retorno" para obtener resultados, si se requieren resultados como consecuencia de alguna solicitud). Esta es también una arquitectura de Python muy sólida para el enhebrado de propósito general (y la expongo extensamente en "Python in a Nutshell", pero ese es otro tema ;-).
Tkinter tiene problemas relacionados con la entrada de varios hilos, utilizo mtTkinter en su lugar, no necesitará cambiar ningún código y todo funcionará bien. Solo importa mtTkinter en lugar de Tkinter.
Puedes obtenerlo aqui: