不支持 C++ 类型作为 pyqtSignal() 类型参数类型

C++ type is not supported as a pyqtSignal() type argument type

我正在尝试在我的 GUI 中实现一个状态机(使用 python3.8 和 Qt5(使用 PyQt5 而不是 PySides!))。我遇到的问题是在添加基于事件的转换时。

使用下面的代码,解释器在第 26 行抱怨:

s1.addTransition(self.btn_start, pyqtSignal("clicked()"), s2)
TypeError: C++ type 'clicked()' is not supported as a pyqtSignal() type argument type
import sys
import logging
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QApplication
from PyQt5.QtCore import QStateMachine, QState, QFinalState, pyqtSignal


class TabTest(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.logger = logging.getLogger("TABTEST")

        self.btn_start = QPushButton("START")
        # self.btn_start.clicked.connect(self.btn_start_clicked)

        layout = QVBoxLayout()
        layout.addWidget(self.btn_start)
        self.setLayout(layout)

        machine = QStateMachine()
        s1 = QState()
        s1.assignProperty(self.btn_start, "TEXT", "CLICK ME")

        s2 = QFinalState()
        s1.addTransition(self.btn_start, pyqtSignal("clicked()"), s2)

        machine.addState(s1)
        machine.addState(s2)
        machine.setInitialState(s1)
        machine.start()

    # def btn_start_clicked(self):
    #     self.logger.info("klikked")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = TabTest()
    main_window.show()
    sys.exit(app.exec_())

我之前用谷歌搜索并阅读了 Whosebug,但所有答案都是针对 Qt4 或正在使用 PySidesQt5Qt4 之间有很多变化。 PySidesPySides.QtCore.SIGNAL,我发现 PyQt5 中的等效项是 PyQt5.QtCore.pyqtSignal,但似乎无法正常工作。

您的代码有 3 个错误:

  • QStateMachine 是一个局部变量,它将立即被销毁以防止观察到所需的行为,因为有 2 个解决方案:设置父级(更改为 QStateMachine(self))或创建它class的成员(将所有 machine 更改为 self.machine)。

  • 如果要分配 属性 则必须尊重名称,在这种情况下 属性 是 "text" 而不是 "TEXT" .

  • 在PyQt5中你必须传递信号,即obj.foo_signal,在你的例子中self.btn_start.clicked.

综合以上,解决方案是:

class TabTest(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.btn_start = QPushButton("START")

        layout = QVBoxLayout(self)
        layout.addWidget(self.btn_start)

        machine = QStateMachine(<b>self</b>)

        s1 = QState()
        s1.assignProperty(self.btn_start, <b>"text"</b>, "CLICK ME")

        s2 = QFinalState()

        s1.addTransition(<b>self.btn_start.clicked</b>, s2)

        # Check if QFinalState was entered
        machine.finished.connect(lambda: print("finished"))

        machine.addState(s1)
        machine.addState(s2)
        machine.setInitialState(s1)
        machine.start()