QtCore.QTimer.singleShot 迭代调用函数时滞后

QtCore.QTimer.singleShot lags when calling a function iteratively

我有 pyqt gui,带有一些通过函数定期更新的文本显示 更新遥测()

我的代码是这样工作的。当用户单击按钮时,将调用 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 秒左右获得一次更新。但是,每隔 10s,整个 gui 会冻结几秒钟,然后更新。我正在做的事情似乎被阻止了。我不确定这是怎么回事。我以为 qtimer.singleshot 会创建一个单独的线程?

有没有更好的方法来做我正在做的事情?

A 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 实际上是在线程中创建的。MyThread.__init__ 仍然在主线程中运行,但 MyThread.run 的内容将在新线程中执行)。您可能还想添加关闭线程的功能,或添加其他我不知道的功能!

如果您在实施过程中遇到问题,请随时 post 关于堆栈溢出的后续问题!