【问题标题】:C++ type is not supported as a pyqtSignal() type argument type不支持 C++ 类型作为 pyqtSignal() 类型参数类型
【发布时间】:2020-05-18 13:28:06
【问题描述】:

我正在尝试在我的 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_())

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

【问题讨论】:

    标签: python python-3.x pyqt5 qt-signals qstatemachine


    【解决方案1】:

    您的代码有 3 个错误:

    • QStateMachine 是一个局部变量,将立即销毁,防止观察到所需的行为,有两种解决方案:设置父级(更改为 QStateMachine(self))或使其成为类的成员(将所有machine 更改为self.machine)。

    • 如果要分配属性,则必须尊重名称,在这种情况下,属性是“文本”而不​​是“文本”。

    • 在 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(self)
    
            s1 = QState()
            s1.assignProperty(self.btn_start, "text", "CLICK ME")
    
            s2 = QFinalState()
    
            s1.addTransition(self.btn_start.clicked, s2)
    
            # Check if QFinalState was entered
            machine.finished.connect(lambda: print("finished"))
    
            machine.addState(s1)
            machine.addState(s2)
            machine.setInitialState(s1)
            machine.start()

    【讨论】:

    • 谢谢! 1)好的,很好,以后会烧死我的。 2)是的,我不太确定那个参数做了什么,所以我还在试验。 3)你知道我可以在文档中的哪里找到这个吗?这是我错过的一件非常重要的事情。
    • @Swedgin 不幸的是没有文档,但前段时间我试过了,我把它提取为 this method 从 C++ 到 python 的翻译,除了不使用 SIGNAL() 宏检查源代码(qstate.sip)
    • 好吧,那太糟糕了。期间我也回了搜索,不过现在更加专注,找到了使用pyqtBoundSignal的函数的定义。事实上,没有文档,因为它下面有一个TODO,哈哈。 riverbankcomputing.com/static/Docs/PyQt5/api/qtcore/…
    • @Swedgin self.btn_start.clicked 实际上是一个pyqtBoundSignal,你找到了文档:-)。 PyQt5 页面似乎已更新,因为几个月前该链接不存在。
    • 是的,我现在也这么认为。我习惯于检查doc.qt.io/qt-5 的文档,但现在显然落后了,我应该使用riverbankcomputing 一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    相关资源
    最近更新 更多