如何使tkinter等待新线程完成?

时间:2019-05-06 15:31:50

标签: python tkinter

如何在函数fix()中执行tkinter,等到label's文本被更改然后再打印end

当前工作:当我单击sub按钮时,将创建新线程并执行for循环。经过10000000次循环后,我的标签将更改为9999999。但是在我更改标签之前,tkinter会打印end

我尝试了t.join(),但是它冻结了GUI。

import tkinter as tk
from tkinter import ttk
import threading

root = tk.Tk()
label = tk.Label(text='vinoth')
label.pack()

def fix():
    a=0
    t = threading.Thread(target=count, args=(a,))
    t.start()
    #t.join()
    print('end')

def count(a):
        for i in range(0,10000000):
            a=i
        label['text'] = a

button = tk.Button(text='sub', command=fix)
button.pack()
dropdown = ttk.Combobox()
dropdown.pack()

root.mainloop()

2 个答案:

答案 0 :(得分:2)

您必须小心使用多线程tkinter应用程序,因为tcl / tk的接口不支持它。这意味着只有主线程才能调用tkinter及其窗口小部件。

也就是说,您可以通过使用after()等线程安全机制或通过全局Queue方法来安排函数定期运行并与线程通信,来解决该限制变量与`Lock'结合使用,以控制对其的并发访问。

这是一个使用后者完成您要完成的任务的示例:

import tkinter as tk
from tkinter import ttk
import threading


POLLING_DELAY = 250  # ms
lock = threading.Lock()  # Lock for shared resources.
finished = False

root = tk.Tk()
label = tk.Label(text='vinoth')
label.pack()

def fix():
    global finished

    with lock:
        finished = False
    t = threading.Thread(target=count)
    t.daemon = True
    root.after(POLLING_DELAY, check_status)  # Start polling.
    t.start()

def check_status():
    with lock:
        if not finished:
            root.after(POLLING_DELAY, check_status)  # Keep polling.
        else:
            print('end')

def count():
    global finished

    for i in range(10000000):
        a = i
    with lock:
        finished = True
        label['text'] = a


button = tk.Button(text='sub', command=fix)
button.pack()
dropdown = ttk.Combobox()
dropdown.pack()

root.mainloop()

答案 1 :(得分:1)

我在while循环中使用root.update()函数进行了尝试。不知道这是马上做的事!但是无论如何都要发布代码:

import tkinter as tk
from tkinter import ttk
import threading

root = tk.Tk()

class test():

    def __init__(self):
        self.label = tk.Label(text='vicks')
        self.label.pack()
        button = tk.Button(text='sub', command=self.fix)
        button.pack()
        dropdown = ttk.Combobox()
        dropdown.pack()

    def fix(self):
        self.finished = False
        t = threading.Thread(target=self.count)
        t.daemon = True
        t.start()
        self.check_status()
        print('end')

    def check_status(self):
        while self.finished is False:  #keeps running until the variable finished becomes True
            root.update()

    def count(self):
        a=0
        for i in range(100000000):
            a = i
        self.label['text'] = a
        self.finished = True

c = test()

root.mainloop()