0

我有一些文本显示的 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 会创建一个单独的线程?

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

4

1 回答 1

1

AQTimer不创建单独的线程。QTimer在给定的超时后简单地在主线程中发出信号。因此,一切(包括您的设备读取代码)仍在主线程中运行。

您应该将从您的设备读取的代码移动到 a并从主线程QThread发出信号,您可以在其中更新您的 GUI。GUI 更新只能从主线程完成。只有信号发射是线程安全的!QThread

下面是一个粗略的实现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 TrueQTimer配置为每 10 秒触发一次(确保QTimer实际上是在线程中创建的。MyThread.__init__仍然在主线程中运行,但 的内容MyThread.run将在新线程中执行线)。您可能还想添加关闭线程的功能,或添加我不知道的其他功能!

如果您的实现有问题,请随时发布有关堆栈溢出的后续问题!

于 2015-08-10T23:28:14.013 回答