【问题标题】:Update Tkinter widget from main thread after worker thread completes工作线程完成后从主线程更新 Tkinter 小部件
【发布时间】:2018-03-29 01:32:45
【问题描述】:

我需要在线程完成后更新 GUI 并从主线程调用此 update_ui 函数(可能是软件中断?)。工作线程如何调用主线程中的函数?

示例代码:

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

【问题讨论】:

    标签: python multithreading python-2.7 tkinter


    【解决方案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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      相关资源
      最近更新 更多