如何从可以动态更新的pyqt5组框发出信号

How to emit a signal from the pyqt5 groupbox that can be updated dynamically

我有读取 10 个 uart 并在 pyqt5 gui 中打印数据的并行线程。但我面临的问题是当所有 10 个作业完成但不是立即完成时,这些组框会更新。

编辑:为了实现并行性,我使用的是 joblib 而不是 pyqt 线程。

我想要实现的是更改 groupbox 属性的状态,例如标签、按钮文本和颜色,但我没有找到如何触发 groupbox 信号发射的好例子。

我是否需要在 groubox 中发出单独的标签、按钮,或者我可以作为一个 groupbox 对象发出?

这是一个极简代码,其中只有两个 groupbx。有人可以帮助如何从 groubox 发出信号并捕获该变化,即下面代码中标签的状态、按钮文本和颜色吗?

下面的示例更新 groubox 没有任何问题,但实际上每个 g1 方法都是 uart 并且它正在阻塞调用。我等到所有作业完成后才能在我的 GUI 上看到更改。

代码

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, pyqtSignal

class Ui_MainWindow(object):
    changedValue = pyqtSignal(int)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(100, 140, 120, 141))
        self.groupBox.setObjectName("groupBox")
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(0, 40, 113, 32))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(0, 90, 113, 32))
        self.pushButton_3.setObjectName("pushButton_3")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(0, 20, 121, 16))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(180, 80, 113, 32))
        self.pushButton.setObjectName("pushButton")
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(230, 140, 120, 141))
        self.groupBox_2.setObjectName("groupBox_2")
        self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_4.setGeometry(QtCore.QRect(0, 40, 113, 32))
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_5.setGeometry(QtCore.QRect(0, 90, 113, 32))
        self.pushButton_5.setObjectName("pushButton_5")
        self.label_2 = QtWidgets.QLabel(self.groupBox_2)
        self.label_2.setGeometry(QtCore.QRect(0, 20, 121, 16))
        self.label_2.setObjectName("label_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(self.groupBox.update)
        self.pushButton.clicked.connect(self.groupBox_2.update)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.groupBox.setTitle(_translate("MainWindow", "UART1"))
        self.pushButton_2.setText(_translate("MainWindow", "Test1"))
        self.pushButton_3.setText(_translate("MainWindow", "Test2"))
        self.label.setText(_translate("MainWindow", "IMEI"))
        self.pushButton.setText(_translate("MainWindow", "START"))
        self.groupBox_2.setTitle(_translate("MainWindow", "UART2"))
        self.pushButton_4.setText(_translate("MainWindow", "Test1"))
        self.pushButton_5.setText(_translate("MainWindow", "Test2"))
        self.label_2.setText(_translate("MainWindow", "IMEI"))

        #Setting a connection here
        self.pushButton.clicked.connect(self.g1)
        self.pushButton.clicked.connect(self.g2)

    def g1(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.pushButton.setText(_translate("MainWindow", "Running"))
        imei = "12345"
        self.label.setText(imei)
        self.changedValue.emit(imei)
        self.pushButton_2.setText(_translate("MainWindow", "Pass"))
        self.pushButton_3.setText(_translate("MainWindow", "FAIL"))
        self.pushButton_3.setStyleSheet("background-color:  rgb(0, 255, 0);")

    def g2(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.pushButton.setText(_translate("MainWindow", "Done"))
        imei = "12345"
        self.label_2.setText("12345")
        self.changedValue.emit(imei)
        self.pushButton_4.setText(_translate("MainWindow", "FAIL"))
        self.pushButton_4.setStyleSheet("background-color:  rgb(0, 255, 0);")
        self.pushButton_5.setText(_translate("MainWindow", "Pass"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

首先,我建议您阅读文档 Using the Generated Code。 PyQt 在这个 post 建议不要修改 Qt Designer 生成的代码,因为它不是一个小部件它只是一个 class 用来填充一个小部件,相反最好创建另一个 class 基于选择的形式并在那里实现逻辑,因为例如你的代码有一个严重的错误:信号只能像小部件一样在 QObject 中创建,但 Ui_MainWindow 不是。

综合以上,解决方案是:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(100, 140, 120, 141))
        self.groupBox.setObjectName("groupBox")
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(0, 40, 113, 32))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(0, 90, 113, 32))
        self.pushButton_3.setObjectName("pushButton_3")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(0, 20, 121, 16))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(180, 80, 113, 32))
        self.pushButton.setObjectName("pushButton")
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(230, 140, 120, 141))
        self.groupBox_2.setObjectName("groupBox_2")
        self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_4.setGeometry(QtCore.QRect(0, 40, 113, 32))
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_5.setGeometry(QtCore.QRect(0, 90, 113, 32))
        self.pushButton_5.setObjectName("pushButton_5")
        self.label_2 = QtWidgets.QLabel(self.groupBox_2)
        self.label_2.setGeometry(QtCore.QRect(0, 20, 121, 16))
        self.label_2.setObjectName("label_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(self.groupBox.update)
        self.pushButton.clicked.connect(self.groupBox_2.update)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.groupBox.setTitle(_translate("MainWindow", "UART1"))
        self.pushButton_2.setText(_translate("MainWindow", "Test1"))
        self.pushButton_3.setText(_translate("MainWindow", "Test2"))
        self.label.setText(_translate("MainWindow", "IMEI"))
        self.pushButton.setText(_translate("MainWindow", "START"))
        self.groupBox_2.setTitle(_translate("MainWindow", "UART2"))
        self.pushButton_4.setText(_translate("MainWindow", "Test1"))
        self.pushButton_5.setText(_translate("MainWindow", "Test2"))
        self.label_2.setText(_translate("MainWindow", "IMEI"))


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    changedValue = QtCore.pyqtSignal(int)

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        #Setting a connection here
        self.pushButton.clicked.connect(self.g1)
        self.pushButton.clicked.connect(self.g2)

    @QtCore.pyqtSlot()
    def g1(self):
        _translate = QtCore.QCoreApplication.translate
        self.pushButton.setText(_translate("MainWindow", "Running"))
        imei = "12345"
        self.label.setText(imei)
        self.changedValue.emit(imei)
        self.pushButton_2.setText("Pass")
        self.pushButton_3.setText(_translate("MainWindow", "FAIL"))
        self.pushButton_3.setStyleSheet("background-color:  rgb(0, 255, 0);")

    @QtCore.pyqtSlot()
    def g2(self):
        _translate = QtCore.QCoreApplication.translate
        self.pushButton.setText(_translate("MainWindow", "Done"))
        imei = "12345"
        self.label_2.setText("12345")
        self.changedValue.emit(imei)
        self.pushButton_4.setText(_translate("MainWindow", "FAIL"))
        self.pushButton_4.setStyleSheet("background-color:  rgb(0, 255, 0);")
        self.pushButton_5.setText(_translate("MainWindow", "Pass"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())