1 回答
TA贡献1811条经验 获得超4个赞
所以我这样做了,但我不知道它是否适合你,或者这是否是一个很好的方法,但它可以像评论中所述那样保护你,它的好处是.after你的函数do_stuff只在需要时被调用.
import tkinter as tk
import time
import threading
def get_data():
time.sleep(3)
print('sleeped 3')
_check.set(1)
def do_stuff():
try:
root.configure(bg='#'+str(_var.get()))
_var.set(_var.get()+101010)
except:
_var.set(101010)
root = tk.Tk()
_check = tk.IntVar(value=0)
_var = tk.IntVar(value=101010)
def callback(event=None, *args):
t1 = threading.Thread(target=get_data)
t1.start()
do_stuff()
_check.trace_add('write', callback) #kepp track of that variable and trigger callback if changed
callback() # start the loop
root.mainloop()
一些研究:
interpreter 仅在创建它的线程中有效,所有 Tk 活动也必须在该线程中发生。这意味着必须在创建解释器的线程中调用主循环。可以从其他线程调用命令;_tkinter 将为解释器线程排队一个事件,然后解释器线程将执行命令并传回结果。
#l1493 var_invoke
The current thread is not the interpreter thread. Marshal the call to the interpreter thread, then wait for completion. */ if (!WaitForMainloop(self)) return NULL;
在 python 线程中使用 intvar-doublevar 是否安全
当您设置一个变量时,它会在与该变量关联的主控件上调用 globalsetvar 方法。_tk.globalsetvar 方法在 C 中实现,并在内部调用 var_invoke,后者在内部调用 WaitForMainLoop,它将尝试安排命令在主线程中执行,如我上面引用的 _tkinter 源中所述。
Start
|
|<----------------------------------------------------------+
v ^
Do I have No[*] Calculate how Sleep for at |
work to do? -----> long I may sleep -----> most that much --->|
| time |
| Yes |
| |
v |
Do one callback |
| |
+-----------------------------------------------------------+
常识
来自错误追踪器:
Tkinter 和线程。
如果你想同时使用 tkinter 和线程,最安全的方法是在主线程中进行所有 tkinter 调用。如果工作线程生成 tkinter 调用所需的数据,请使用 queue.Queue 将数据发送到主线程。为了彻底关闭,添加一个方法来等待线程停止并在按下窗口关闭按钮 [X] 时调用它。
效果机器人
只需在主线程中运行所有 UI 代码,让编写器写入一个 Queue 对象;例如
结论
你做事的方式和我做事的方式似乎很理想,但它们似乎一点也没错。这取决于需要什么。
添加回答
举报