【发布时间】:2021-12-12 22:31:37
【问题描述】:
尝试更新在具有“main”函数变量的线程上运行的 tkinter“textvariable”。我实现了一个基于线程的解决方案,因此 tkinter 主循环之后的代码可以运行:https://stackoverflow.com/a/1835036/15409926。
请分享我如何解决此错误。如果这不是更新“textvariable”的最简单方法,请分享替代方法。
代码:
from tkinter import *
from threading import Thread
class GUI(Thread):
def __init__(self):
Thread.__init__(self)
self.start()
def run(self):
self.root = Tk()
self.var = StringVar()
self.var.set("Initiated")
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
width = screen_width*.12
height = screen_height
x = screen_width - width
y = screen_height*.025
self.root.geometry('%dx%d+%d+%d' % (width, height, x, y))
label = Label(self.root, textvariable= self.var)
label.pack()
self.root.mainloop()
gui = GUI()
def main():
for i in range(1000):
gui.var.set(f'Current Iteration: {i}')
if __name__ == '__main__':
main()
窗口不更新: Tkinter window displays initial 'textvariable'
错误:
Traceback (most recent call last):
File "test.py", line 36, in <module>
main()
File "test.py", line 33, in main
gui.var.set(f'Current Iteration: {i}')
AttributeError: 'GUI' object has no attribute 'var'
【问题讨论】:
-
首先,不要在单独的线程中运行
tkinter方法。您可以不在主线程中运行所有tkinter的东西,但不要将其方法分离到不同的线程,这可能会破坏它。第二直接关于你的问题。在开始循环之前和循环中(否则太快)在main函数中放入一些time.sleep,因为线程启动需要一些时间 -
在您的示例中,您可以使用
root.after(millisecond, function)insread ofthreading- 但如果您有需要更多时间的功能,那么您应该使用queue向线程发送新值,它应该使用@ 987654332@检查queue中是否有新值并直接在线程中更新值。 -
@furas 真正的函数是长时间运行的,所以使用 after 会一直暂停函数,对吧?
-
如果你运行长时间运行的代码,那么它应该在单独的线程中运行,它应该使用
queue将值发送到带有 GUI 的线程,并且这个线程应该使用 after 定期检查是否有新的queue中的信息并更新 GUI 中的值 - 因此它将在与 GUI 相同的线程中更新它。
标签: python multithreading tkinter