繁体   English   中英

如何在 python 线程中使用计时器或等效项而不阻塞 GUI

[英]How to use a timer or equivalent within a python thread without blocking the GUI

我正在使用 PyQT 框架编写基于 GUI 的应用程序,该框架连接到设备、发送命令、读取相应数据并将其实时显示到表格、图形小部件和文件中。

单击运行按钮后,它会启动一个线程,该线程根据程序表发送外部设备命令,并将带有数据的信号发送到各种方法以更改 GUI。

单击运行按钮时,它将执行以下几行:

worker = Worker(self.runProcedure)
worker.signals.updateResults.connect(self.updateResultsTable)
worker.signals.writeResults.connect(self.writeResultsFile)
worker.signals.finished.connect(self.procedure_complete) 
     
self.threadpool.start(worker)

runProcedure 中的命令从程序表发送到设备,并且使用类似于下面列出的代码将从设备读取的数据放入列表“hfData”中:

while float(currentForceReading) <= float(target) and stopAlarm == 0:
    ts = dt.now().timestamp()
    hfData = (connection.readline()).split()
    updateResults_callback.emit(ts, hfData) #method to update results table and graphs
    writeResults_callback.emit(ts, hfData)  #method to write results to a file

应用程序中的一个选项是保持一段时间,在该时间段内它继续从设备收集数据而不发送新命令。

我正在寻找一种在此保持时间内继续进行测量并继续更新 GUI 的方法。

我试图实现以下代码,但是这个 while 循环阻止了 GUI 更新:

stepHoldTime = float(procedureModel.data(procedureModel.index(row,4), Qt.DisplayRole))
if(stepHoldTime != 0):
    endTime = time.monotonic() + stepHoldTime
    while(time.monotonic() < endTime):
        ts = dt.now().timestamp()
        hfData = (connection.readline()).split()
        updateResults_callback.emit(ts,hfData)

有没有正确的方法来实现这个功能?

您可以运行QTimer而不是while -loop,它将每隔几毫秒执行一次代码。

这是一个最小的例子,它展示了如何每 1000 毫秒运行一次 function 并在 label 中更新时间。

from PyQt5.QtWidgets import QApplication, QLabel
from PyQt5.QtCore import QTimer, QDateTime

class Window(QLabel):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.showTime()
        
        help(QTimer)
        self.timer = QTimer()
        self.timer.timeout.connect(self.showTime)
        self.timer.start(1000)

    def showTime(self):
        text = QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss')
        self.setText(text)

if __name__ == '__main__':
    app = QApplication([])
    win = Window()
    win.show()
    app.exec()

但是您的问题可能更复杂,可能需要更复杂的解决方案。 您可能必须展示我们可以运行并查看问题的最少工作代码 - 并测试一些解决问题的想法。

您可以从单独的线程启动您的“阅读器”

class YourUi(QtWidgets.QMainWindow):
    update_data = QtCore.pyqtSignal(str)

    def __init__(self):
        super(YourUi, self).__init__()
        self.update_data.connect(self.do_update_data)

        t = threading.Thread(target=self.update_worker, args=(self.update_data,), daemon=True)
        t.start()

    @staticmethod
    def update_worker(signal):
        connection = create_conncetion()
        while True:
            hfData = (connection.readline()).split()
            signal.emit(hfData)
            time.sleep(0.1)

    def do_update_data(self, hf_data):
        # access GUI elemetns from main thread to prevent freezing
        self.some_qt_label.setText(str(hf_data))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM