2017-10-17 109 views
1

线程完成后我需要更新GUI并从主线程调用此update_ui函数(如软件中断也许?)。工作线程如何在主线程中调用一个函数?在工作线程完成后从主线程更新Tkinter小部件

示例代码:

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

我试图用队列或两个线程访问的任何标志,但我必须不断等待/民意调查,以检查是否值已更新,然后调用函数 - 此等待使UI无响应。例如

flag = True 

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

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

回答

1

您的代码似乎有些假设。这里有一些完成了你所描述的事情。它创建三个标签并初始化他们的文本。然后它启动三个线程。每个线程在一段时间后更新与主线程中创建的标签相关的tkinter变量。现在如果主线程真的需要更新,排队确实有效,但是必须修改程序来完成更新。

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() 
相关问题