作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图从一个单独的线程在 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 线程 提交一个事件>事件生成。这使您可以在没有线程错误的情况下更新小部件。
event_generate
触发主线程中的事件。使用 state
属性将数据(数字)传递给事件。这是一个例子:
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/
我是一名优秀的程序员,十分优秀!