2017-10-17 6 views
1

Je dois mettre à jour l'interface graphique après la fin d'un thread et appeler cette fonction update_ui du thread principal (comme une interruption de logiciel peut-être?). Comment un thread de travail peut-il appeler une fonction dans le thread principal?Mettre à jour le widget Tkinter à partir du thread principal une fois le thread de travail terminé

Exemple de code:

def thread(): 
    ...some long task 
    update_ui() #But call this in main thread somehow 

def main(): 
    start_new_thread(thread) 
    ...other functionality 

def update_ui(): 
    Tkinter_widget.update() 

J'ai essayé d'utiliser la file d'attente ou un drapeau accessible aux deux fils, mais je dois attendre/poll en permanence pour vérifier si la valeur a été mise à jour et appeler la fonction - cette attente rend l'interface utilisateur inerte. par exemple.

flag = True 

def thread(): 
    ...some long task 
    flag = False 

def main(): 
    start_new_thread(thread) 
    while(flag): sleep(1) 
    update_ui() 
    ...other functionality 

Répondre

1

Votre code semble être quelque peu hypothétique. Voici quelques-uns qui accomplit cela fait ce que vous décrivez. Il crée trois étiquettes et initialise leur texte. Il commence alors trois threads. Chaque thread met à jour la variable tkinter associée à l'étiquette créée dans le thread principal après un certain temps. Maintenant, si le thread principal a vraiment besoin de faire la mise à jour, la mise en file d'attente fonctionne, mais le programme doit être modifié pour accomplir cela.

import threading 
import time 
from tkinter import * 
import queue 
import sys 

def createGUI(master, widget_var): 
    for i in range(3): 
     Label(master, textvariable=widget_var[i]).grid(row=i, column=0) 
     widget_var[i].set("Thread " + str(i) + " started") 

def sometask(thread_id, delay, queue): 
    print("Delaying", delay) 
    time.sleep(delay) 
    tdict = {'id': thread_id, 'message': 'success'} 
    # You can put simple strings/ints, whatever in the queue instead 
    queue.put(tdict) 
    return 

def updateGUI(master, q, widget_var, td): 
    if not q.empty(): 
     tdict = q.get() 
     widget_var[tdict['id']].set("Thread " + str(tdict['id']) + " completed with status: " + tdict['message']) 
     td.append(1) 
    if len(td) == 3: 
     print("All threads completed") 
     master.after(1000, timedExit) 
    else: 
     master.after(100, lambda w=master,que=q,v=widget_var, tcount=td: updateGUI(w,que,v,td)) 

def timedExit(): 
    sys.exit() 

root = Tk() 
message_q = queue.Queue() 

widget_var = [] 
threads_done = [] 
for i in range(3): 
    v = StringVar() 
    widget_var.append(v) 
    t = threading.Thread(target=sometask, args=(i, 3 + i * 3, message_q)) 
    t.start() 

createGUI(root, widget_var) 
updateGUI(root,message_q, widget_var, threads_done) 
root.mainloop()