2010-08-25 16 views
7

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.El script de Tkinter con subprocesos se bloquea al crear el segundo widget de Toplevel

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

Respuesta

22

Tkinter está diseñado para funcionar desde el hilo principal, solamente. Ver the docs:

Sólo tiene que ejecutar todo el código de interfaz de usuario en el principal hilo, y dejar que los escritores escriben a un objeto cola; p.ej.

... y sigue un ejemplo sustancial, que muestra los hilos secundarios que escriben solicitudes a una cola, y el lazo principal es el único responsable de todas las interacciones directas con Tk.

Muchos objetos y subsistemas no les gusta recibir solicitudes desde varios varios hilos, y en el caso de herramientas GUI que no es raro necesitar especificamente para usar el hilo principal solamente.

La arquitectura de Python correcta para este problema es siempre 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 ;-).

+0

Gracias por la respuesta rápida. Revisaré los documentos. – user430825

+0

@ usuario, de nada! –

+9

He encontrado esta restricción y es exactamente la táctica que uso. Tengo un método que verifica todas las colas. Luego registro ese método con el bucle principal de Tkinter llamando a root.after (ms, my_method).La última llamada en my_method es otra llamada a root.after para que my_method se vuelva a registrar continuamente con el bucle principal. Es importante que las excepciones en my_method no te hagan perder el registro con el mainloop. Es posible que desee poner su llamada a root.after en la parte final de try/finally. –

0

¿Hay alguna razón por la que desee (o crea que necesita) un bucle de evento por cada ventana de nivel? 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 bucle de evento único y ejecutarlo en el hilo principal.

+0

Muchas gracias por las respuestas, he podido resolver el problema gracias a ustedes, nunca había publicado en un lugar como este y me ha sorprendido gratamente con tanta ayuda. – user430825

6

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.

Puede obtenerlo aquí:

http://tkinter.unpythonic.net/wiki/mtTkinter

+0

¿funciona con python 3? –

Cuestiones relacionadas