Creo que no debe ejecutar el bucle principal en un hilo diferente. AFAIK, el bucle principal debería ejecutarse en el mismo hilo que creó el widget.
Los kits de herramientas de GUI con los que estoy familiarizado (Tkinter, .NET Windows Forms) son de esa manera: Puede manipular la GUI desde un único subproceso.
En Linux, el código lanza una excepción:
self.tk.mainloop(n)
RuntimeError: Calling Tcl from different appartment
una de las siguientes funcionará (no hay temas adicionales):
if __name__ == '__main__':
t = tk.Tk()
t.iconbitmap('icon.ico')
b = tk.Button(text='test', command=exit)
b.grid(row=0)
t.mainloop()
Con rosca adicional:
def threadmain():
t = tk.Tk()
t.iconbitmap('icon.ico')
b = tk.Button(text='test', command=exit)
b.grid(row=0)
t.mainloop()
if __name__ == '__main__':
thread.start_new_thread(threadmain,())
while 1:
sleep(1)
Si necesita comunicarse con tkinter desde fuera del hilo de tkinter, sugiero que configure un temporizador que verifique la cola de trabajo.
Aquí se muestra un ejemplo:
import Tkinter as tk
import thread
from time import sleep
import Queue
request_queue = Queue.Queue()
result_queue = Queue.Queue()
def submit_to_tkinter(callable, *args, **kwargs):
request_queue.put((callable, args, kwargs))
return result_queue.get()
t = None
def threadmain():
global t
def timertick():
try:
callable, args, kwargs = request_queue.get_nowait()
except Queue.Empty:
pass
else:
print "something in queue"
retval = callable(*args, **kwargs)
result_queue.put(retval)
t.after(500, timertick)
t = tk.Tk()
t.configure(width=640, height=480)
b = tk.Button(text='test', name='button', command=exit)
b.place(x=0, y=0)
timertick()
t.mainloop()
def foo():
t.title("Hello world")
def bar(button_text):
t.children["button"].configure(text=button_text)
def get_button_text():
return t.children["button"]["text"]
if __name__ == '__main__':
thread.start_new_thread(threadmain,())
trigger = 0
while 1:
trigger += 1
if trigger == 3:
submit_to_tkinter(foo)
if trigger == 5:
submit_to_tkinter(bar, "changed")
if trigger == 7:
print submit_to_tkinter(get_button_text)
sleep(1)
Bueno usted ha golpeado el clavo en la cabeza, funciona ... pero ha sufrido de no proporcionar suficiente información. Mi razonamiento es que quiero poder hacer cosas para tkinter donde el ciclo while es ... Siendo un poco nuevo en SO, ¿debería aceptar su respuesta y hacer otra pregunta más detallada? – burito
Hola, he actualizado mi respuesta con una sugerencia y un ejemplo de código para eso. El ciclo while ahora llama a unos pocos métodos en el subproceso tkinter, utilizando colas de solicitud/respuesta. – codeape
BTW, para el código de producción, sugiero que encapsule la ventana, el hilo y las colas de Tkinter en una clase. Esto para evitar los globales que tenemos ahora: request_queue, response_queue y t. También necesita algún tipo de manejo de errores alrededor de los invocables (* args, ** kwargs). – codeape