python - 如何让 tkinter 等待新线程完成?
问题描述
如何使函数中的 tkinter 执行fix()
等到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()
解决方案
您必须小心多线程tkinter
应用程序,因为 tcl/tk 的接口不支持它。这意味着只有主线程可以调用tkinter
及其小部件。
也就是说,您可以通过使用通用after()
方法来安排函数定期运行并与线程通信,或者通过线程安全机制(如 aQueue
或通过全局变量加上 aLock
来控制对它或它们的并发访问)来解决此限制。
这是使用后者来完成您要完成的工作的示例:
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()
推荐阅读
- c - 指针出于某种原因显示垃圾
- php - 每天通过 php 和 Javascript 创建一个日志文件
- python - 使用 .apply(pd.Timestamp) 时如何指定日期标准。Python 在 2018 年 11 月 12 日混淆日期和月份
- indexing - sqlite3 DB 不使用索引,除非被清理
- scala - 在构建时从 scala 案例类生成 avsc avro 模式
- acumatica - Acumatica GI 看到软删除的数据
- batch-file - Saxon:result-document() 函数失败且没有错误消息
- google-cloud-firestore - Google Cloud Firestore/Datastore 中的不同阶段(例如开发、生产)
- r - 获取 RStudio Server 开源版本以使用替代 gcc 版本
- amazon-web-services - 在厨师中创建 cron