serrature Tkinter Python quando un'icona viene caricato e tk.mainloop è in una filettatura
-
20-09-2019 - |
Domanda
Ecco il banco di prova ...
import Tkinter as tk
import thread
from time import sleep
if __name__ == '__main__':
t = tk.Tk()
thread.start_new_thread(t.mainloop, ())
# t.iconbitmap('icon.ico')
b = tk.Button(text='test', command=exit)
b.grid(row=0)
while 1:
sleep(1)
Questo codice funziona. Rimuovere il commento dalla linea t.iconbitmap e si blocca. Ri-organizzare in qualsiasi modo che ti piace; si blocca.
Come posso evitare tk.mainloop bloccare la GIL quando c'è un'icona presente?
L'obiettivo è win32 e Python 2.6.2.
Soluzione
Credo che non si deve eseguire il ciclo principale su un thread diverso. AFAIK, il ciclo principale deve essere eseguito sullo stesso filo che ha creato il gadget.
I toolkit GUI che mi è familiare (Tkinter, NET Windows Forms) sono in questo modo: È possibile manipolare la GUI da un solo thread
.In Linux, il codice solleva un'eccezione:
self.tk.mainloop(n) RuntimeError: Calling Tcl from different appartment
Uno dei seguenti funzionerà (nessun thread aggiuntivi):
if __name__ == '__main__':
t = tk.Tk()
t.iconbitmap('icon.ico')
b = tk.Button(text='test', command=exit)
b.grid(row=0)
t.mainloop()
Con filo in più:
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)
Se avete bisogno di fare comunicare con tkinter da fuori discussione Tkinter, vi consiglio di impostare un timer che controlla una coda di lavoro.
Ecco un esempio:
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)