Ejecutando un formulario Tkinter en un hilo separado

He escrito un módulo corto al que se puede pasar una imagen y simplemente crea una ventana Tkinter y la muestra. El problema que tengo es que incluso cuando instalo y llamo al método que muestra la imagen en un hilo separado, el progtwig principal no continuará hasta que se cierre la ventana de Tkinter.

Aquí está mi módulo:

import Image, ImageTk import Tkinter class Viewer(Tkinter.Tk): def __init__(self,parent): Tkinter.Tk.__init__(self,parent) self.parent = parent self.initialize() def initialize(self): self.grid() def show(self,img): self.to_display = ImageTk.PhotoImage(img) self.label_image = Tkinter.Label(self,image=self.to_display) self.label_image.grid(column = 0, row = 0, sticky = "NSEW") self.mainloop() 

Parece que funciona bien, excepto cuando lo llamo desde mi progtwig de prueba como el que se muestra a continuación, no parece permitir que mi progtwig de prueba continúe, incluso cuando se inicia en un hilo diferente.

 import Image from viewer import Viewer import threading def showimage(im): view = Viewer(None) view.show(im) if __name__ == "__main__": im = Image.open("gaben.jpg") t = threading.Thread(showimage(im)) t.start() print "Program keeps going..." 

Creo que tal vez mi problema sea que debería estar creando un nuevo hilo dentro del propio módulo, pero quería simplemente intentarlo y mantenerlo simple, ya que soy nuevo en Python.

De todos modos, gracias de antemano por cualquier ayuda.

editar: Para mayor claridad, solo estoy tratando de hacer un módulo que muestre una imagen en una ventana de Tkinter, de modo que pueda usar este módulo cada vez que quiera mostrar una imagen. El problema que tengo es que cada vez que un progtwig utiliza este módulo, no puede reanudarse hasta que se cierre la ventana de Tkinter.

Por sus comentarios suena como si no necesitara una GUI en absoluto. Simplemente escriba la imagen en el disco y llame a un visor externo.

En la mayoría de los sistemas debería ser posible iniciar el visor predeterminado utilizando algo como esto:

 import subprocess subprocess.Popen("yourimage.png") 

Tkinter no es seguro para subprocesos, y el consenso general es que Tkinter no funciona en un subproceso no principal. Si reescribe su código para que Tkinter se ejecute en el hilo principal, puede hacer que sus trabajadores se ejecuten en otros hilos.

La principal advertencia es que los trabajadores no pueden interactuar con los widgets de Tkinter. Tendrán que escribir datos en una cola, y su hilo GUI principal tendrá que sondear esa cola.

Si todo lo que estás haciendo es mostrar imágenes, probablemente no necesites ningún hilo. El subprocesamiento solo es útil cuando tiene un proceso de ejecución prolongado que, de lo contrario, bloquearía la GUI. Tkinter puede manejar fácilmente cientos de imágenes y ventanas sin romper el sudor.

Por lo que puedo decir, a Tkinter no le gusta jugar en otros hilos. Ver esta publicación … Necesito un poco de ayuda con Python, Tkinter y threading

La solución consiste en crear un nivel (posiblemente oculto) en el hilo principal, generar un hilo separado para abrir imágenes, etc., y usar una cola compartida para enviar mensajes de vuelta al hilo Tk.

¿Necesitas usar Tkinter para tu proyecto? Me gusta Tkinter. Es “rápido y sucio”. – pero hay (muchos) casos donde otros kits de GUI son el camino a seguir.

He intentado ejecutar tkinter desde un subproceso separado, no es una buena idea, se congela. Hay una solución que funcionó. Ejecute el gui en el hilo principal y envíe eventos al gui principal. Este es un ejemplo similar, solo muestra una etiqueta.

 import Tkinter as t global root; root = t.Tk() root.title("Control center") root.mainloop() def new_window(*args): global root print "new window" window = t.Toplevel(root) label = t.Label(window, text="my new window") label.pack(side="top", fill="both", padx=10, pady=10) window.mainloop() root.bind("<>",new_window) #this can be run in another thread root.event_generate("<>",when="tail")