我有一些文本显示的pyqt gui,它会通过函数定期更新 updateTelemetry()
以下是我的代码的工作原理。当用户单击该按钮时,将调用buttonHandler。并且每10秒迭代地调用updateTelemetry。:
def buttonHandler(self):
self.monitor=true
self.updateTelemetry()
def updateTelemetry(self):
try:
#update values on gui
finally:
if self.monitor:
QtCore.QTimer.singleShot(10000, self.updateTelemetry)
这种方法很有效,让我每10秒左右就能得到一次更新。然而,每隔10秒,整个gui冻结几秒钟然后更新。我正在做的事情似乎在阻止。我不确定那是怎么回事。我以为qtimer.singleshot会创建一个单独的线程吗?
有没有更好的方法来做我正在做的事情?
答案 0 :(得分:1)
QTimer
不会创建单独的线程。 QTimer
只是在给定的超时后在主线程中发出一个信号。因此,所有内容(包括您的设备读取代码)仍在主线程中运行。
您应该将从设备读取的代码移动到QThread
,并从QThread
向主线程发出信号,您可以在其中更新GUI。 GUI更新只能从主线程完成。只有信号发射是线程安全的!
以下是QThread
的粗略实现。
class MyThread(QObject):
send_data_to_gui = pyqtSignal(str)
def __init__(self,*args,**kwargs):
QObject.__init__(self,*args,**kwargs)
@pyqtSlot()
def run(self):
while True:
# get data from device
self.send_data_to_gui.emit(data_from_device)
time.sleep(10)
...
thread = QThread()
my_thread = MyThread()
my_thread.send_data_to_gui.connect(my_slot)
my_thread.moveToThread(thread)
thread.started.connect(my_thread.run)
thread.start()
请注意,在它的当前形式中,QThread
实际上拥有它自己的事件循环,因此您可以执行各种复杂的操作(但while True
此时正在阻止事件循环)。由于线程具有独立的事件循环,您可以将while True
替换为QTimer
,配置为每10秒触发一次(确保在线程中实际创建了QTimer
。{ {1}}仍然在主线程中运行,但MyThread.__init__
的内容将在新线程中执行。您还可能希望添加关闭线程的功能,或添加我不知道的其他功能!
如果您的实施有问题,请随时发布有关堆栈溢出的后续问题!