当我使用线程时,PyQt5 中没有更新 GUI

Posted

技术标签:

【中文标题】当我使用线程时,PyQt5 中没有更新 GUI【英文标题】:No update GUI in PyQt5 When I use threads 【发布时间】:2019-03-08 16:40:00 【问题描述】:

我从带有 Modbus Lib 的控制器中读取了有关温度和电压的信息。当我在“尝试...除”中执行此操作时,一切正常。 但是当我在 Thread 的 while 循环中执行此操作时,GUI 会保持不变约 20 秒。 但是,温度打印工作正常。 然后,当我单击 GUI 上的按钮时,GUI 信息就会更新。

from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication
import time
from modbusFunction import *

第一个带有 Try except 的代码和第二个带有 While 循环和线程的代码:

class test(QtWidgets.QMainWindow):
    def __init__(self):
        super(test, self).__init__()
        uic.loadUi('ui/test.ui', self)
        self.readTemp()

    def readTemp(self):
        try:
            temp = modbusFunction.modbusReadRegister(self, '192.168.1.13', 502, 0x1192, 1)
            print(temp[0])
            self.supplyTempResualt.setText(str(temp[0]))
        except Exception as err:
            print(err)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = test()
    window.show()
    sys.exit(app.exec_())

第二个密码:

from threading import Thread

class test(QtWidgets.QMainWindow):
    def __init__(self):
        super(test, self).__init__()
        uic.loadUi('ui/test.ui', self)

        t = Thread(target = self.readTemp)
        t.daemon = True
        t.start()

    def readTemp(self):
        while True:
            try:
                temp = modbusFunction.modbusReadRegister(self, '192.168.1.13', 502, 0x1192, 1)
                print(temp[0])
                self.supplyTempResualt.setText(str(temp[0]))
            except Exception as err:
                print(err)
            time.sleep(1)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = test()
    window.show()
    sys.exit(app.exec_())

【问题讨论】:

我的回答有用吗? 【参考方案1】:

你不应该直接从另一个线程更新GUI,更新有以下方法:

1. pyqtSignal()

class test(QtWidgets.QMainWindow):
    textChanged = QtCore.pyqtSignal()

    def __init__(self):
        super(test, self).__init__()
        uic.loadUi('ui/test.ui', self)
        self.textChanged.connect(self.supplyTempResualt.setText)

        t = Thread(target = self.readTemp)
        t.daemon = True
        t.start()

    def readTemp(self):
        while True:
            try:
                temp = modbusFunction.modbusReadRegister(self, '192.168.1.13', 502, 0x1192, 1)
                print(temp[0])
                self.textChanged.emit(str(temp[0]))
            except Exception as err:
                print(err)
            time.sleep(1)

2。 QMetaObject::invokeMethod

def readTemp(self):
    while True:
        try:
            temp = modbusFunction.modbusReadRegister(self, '192.168.1.13', 502, 0x1192, 1)
            print(temp[0])
            QtCore.QMetaObject.invokeMethod(self.supplyTempResualt, "setText",
                QtCore.Qt.QueuedConnection, QtCore.Q_ARG(str, str(temp[0])))
        except Exception as err:
            print(err)
        time.sleep(1)

3. functools.partial 和 QTimer.singleShot()

from functools import partial
# ...
def readTemp(self):
    while True:
        try:
            temp = modbusFunction.modbusReadRegister(self, '192.168.1.13', 502, 0x1192, 1)
            print(temp[0])
            QtCore.QTimer.singleShot(0, partial(self.supplyTempResualt.setText, str(temp[0])))
        except Exception as err:
            print(err)
        time.sleep(1)

【讨论】:

以上是关于当我使用线程时,PyQt5 中没有更新 GUI的主要内容,如果未能解决你的问题,请参考以下文章

根据来自scrapy的信号更新主线程内的PyQt5 Gui

Pyqt5 Qtimer理解

在 PyQt5 中通过命令行调用外部程序时,有没有办法阻止 GUI 冻结?

如何使用pytest正确退出队列和Qthread进行测试?

使用 pyqt5 gui 创建一个 exe 文件

是否可以从 PyQt5 中的线程获取数组?