gpt4 book ai didi

python - 从运行命令的单独线程更新 Tkinter GUI

转载 作者:行者123 更新时间:2023-12-05 02:48:50 26 4
gpt4 key购买 nike

我试图从一个单独的线程在 Tkinter 中打包一些东西。我不断收到 RuntimeError

具体来说:RuntimeError: main thread is not in main loop

问题是:如何从单独的线程更新 GUI(主循环)?

问题来源:

    def protocol(self, scheduleName): #ran as thread
print("Getting courses")
self.coursesLabel.pack() #throws the error
...

我希望能够将此线程中的项目打包到 mainloop()。我不确定如何在两个线程之间传输它。

在此先感谢您的帮助!

编辑:这些已经存在的问题中的大多数都会回答同时运行两个独立 GUI 的人。我只需要知道如何将事物从一个线程打包到另一个线程,而不是像同时运行两个 GUI 这样复杂的事情。大多数答案也使用了队列,我想知道是否有更优雅的方法来从单独的线程中打包东西。

最佳答案

tkinter 中,您可以使用 后台线程GUI 线程 提交一个事件>事件生成。这使您可以在没有线程错误的情况下更新小部件。

  1. 在主线程中创建 tkinter 对象
  2. 将根绑定(bind)到虚拟事件(即 << event1 >>),指定事件处理程序。事件名称中需要箭头括号。
  3. 启动后台线程
  4. 在后台线程中,使用event_generate 触发主线程中的事件。使用 state 属性将数据(数字)传递给事件。
  5. 在事件处理器中,处理事件

这是一个例子:

from tkinter import *
import datetime
import threading
import time

root = Tk()
root.title("Thread Test")
print('Main Thread', threading.get_ident()) # main thread id

def timecnt(): # runs in background thread
print('Timer Thread',threading.get_ident()) # background thread id
for x in range(10):
root.event_generate("<<event1>>", when="tail", state=123) # trigger event in main thread
txtvar.set(' '*15 + str(x)) # update text entry from background thread
time.sleep(1) # one second

def eventhandler(evt): # runs in main thread
print('Event Thread',threading.get_ident()) # event thread id (same as main)
print(evt.state) # 123, data from event
string = datetime.datetime.now().strftime('%I:%M:%S %p')
lbl.config(text=string) # update widget
#txtvar.set(' '*15 + str(evt.state)) # update text entry in main thread

lbl = Label(root, text='Start') # label in main thread
lbl.place(x=0, y=0, relwidth=1, relheight=.5)

txtvar = StringVar() # var for text entry
txt = Entry(root, textvariable=txtvar) # in main thread
txt.place(relx = 0.5, rely = 0.75, relwidth=.5, anchor = CENTER)

thd = threading.Thread(target=timecnt) # timer thread
thd.daemon = True
thd.start() # start timer loop

root.bind("<<event1>>", eventhandler) # event triggered by background thread
root.mainloop()
thd.join() # not needed

输出(注意主线程和事件线程是一样的)

Main Thread 5348
Timer Thread 33016
Event Thread 5348
......

我添加了一个 Entry 小部件来测试 StringVar 是否可以从后台线程更新。它对我有用,但如果您愿意,可以更新事件处理程序中的字符串。请注意,从多个后台线程更新字符串可能会出现问题,应使用线程锁。

请注意,如果后台线程自行退出,则不会出现错误。如果您在应用程序退出前关闭它,您将看到“主线程”错误。

关于python - 从运行命令的单独线程更新 Tkinter GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64287940/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com