我需要从另一个线程向tkinter发送更新,应该立即处理。每当我尝试多线程时,可悲的是Tkinter会死机。
我已经阅读了多个Tkinter线程页面,但是没有找到任何有效的方法,因为大多数页面尝试在 button.click()上创建一个新线程,但没有在这里提供帮助。
我尝试不调用 .mainloop()而是在每次更新进来时自己调用更新函数:
#GUI
def update(self, string):
self._interactor.config(text=string)
#interactor is a button
self._tk.update_idletasks()
self._tk.update()
这很好,直到我在master中使用带有sleep()的循环来不断更新文本。 GUI和master在sleep()期间被冻结。 因此,我尝试使用threaded timer as discussed here。
#MASTER
gui=gui_remote(self)
def changetext():
text=self.gettextsomewhere()
self._gui.update(text)
loop=RepeatedTimer(5, changetext)
但这只会导致Tkinter引发以下错误:
RuntimeError:主线程不在主循环中
如何解决这个问题很困难。可以在主线程上调用GUI类,并且仍然可以正确访问其功能吗?
对于我的项目,我需要一个按钮,它代表多个按钮。
每y(例如1.5)秒,显示的文本应从外部更新为新的文本。
另外,我想将GUI,Controller和Data分开(使用蓝图方法),以便以后对它们中的每个进行调整都更加容易。
我已经使用 TK的.after()函数使它起作用,但是我不得不同时使用GUI和控制功能。
具有一个GUI类,该类可以通过简单的公共函数从另一个对象更新。另一个对象(主对象)应该能够创建一个GUI对象,并每隔y秒用新数据调用GUI的更新函数。 单击GUI按钮时,每次只需在master上调用某个方法:
#GUI example
from tkinter import Tk, Button, Frame, Label
class gui_sample:
def __init__(self, master):
"""This is the very simple GUI"""
self._master=master
self._tk=Tk()
self._interactor= Button(self._tk, text="Apfelsaft", command=self._click)
self._interactor.pack()
self._tk.mainloop()
def update(self, string):
"""Handle interactor update"""
self._interactor.config(text=string)
def _click(self):
self._master.click()
#MASTER
from gui_module import *
class Controller:
def __init__(self):
self._gui=gui_sample(self)
self._run()
def _run(self):
#call this every 5 seconds
new_text=self.gettextfromsomewhere()
self._gui.update(new_text)
def click():
#do something
pass
#this code is just a blueprint it probably does nothing
我不希望母版使用TK功能,因为稍后我可能会切换到另一个UI模块并保留母版的功能。主机将不断循环显示接下来显示的内容,并且需要同时进行访问。与sleep()
一起使用循环不是一个好主意,因为它们会同时阻塞主程序和GUI。调用.mainloop()
也是有问题的,因为它将阻塞所有其他程序。 gui应该始终响应更新,而不要求更新。