Python PySide2中QScxmlStateMachine.connectToEvent的奇怪行为

Python PySide2中QScxmlStateMachine.connectToEvent的奇怪行为,python,qml,pyside2,scxml,Python,Qml,Pyside2,Scxml,我正在尝试编写一个桌面应用程序,在后端使用Python,在前端使用QML,并使用scxml创建状态机。我正在使用PySide2。我的意图是通过状态机描述应用程序的逻辑。根据状态,QML中的UI应该做出相应的反应。此外,后端应根据输入的状态等执行方法 我的项目由3个文件组成:main.py带有后端逻辑,ui.qml带有ui,stateMachine.scxml带有状态机 main.py的内容: from PySide2.QtScxml import QScxmlStateMachine from

我正在尝试编写一个桌面应用程序,在后端使用Python,在前端使用QML,并使用scxml创建状态机。我正在使用PySide2。我的意图是通过状态机描述应用程序的逻辑。根据状态,QML中的UI应该做出相应的反应。此外,后端应根据输入的状态等执行方法

我的项目由3个文件组成:
main.py
带有后端逻辑,
ui.qml
带有ui,
stateMachine.scxml
带有状态机

main.py的内容

from PySide2.QtScxml import QScxmlStateMachine
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QUrl, QObject, Slot
from PySide2.QtQml import QQmlApplicationEngine


class BackEnd(QObject):
    def __init__(self):
        super().__init__()

    @Slot()
    def ev_slot(self):
        '''method called on event t1'''
        print('event t1')

    @Slot(bool)
    def st_slot(self, active):
        '''method called on entering and exiting state s2'''
        if active:
            print('s2 entered')
        else:
            print('s2 exited')


app = QApplication([])
qml_url = QUrl("ui.qml")

engine = QQmlApplicationEngine()

# loading state machine
my_state_machine = QScxmlStateMachine.fromFile('stateMachine.scxml')

backend = BackEnd()

# registering state machine in QML context
engine.rootContext().setContextProperty("stateMachine", my_state_machine)
# connecting event of state machine to method of backend
conn1 = my_state_machine.connectToEvent("t1", backend, "aev_slot()")
# connecting state of state machine to method of backend
conn2 = my_state_machine.connectToState("s2", backend, "ast_slot(bool)")

my_state_machine.start()

engine.load(qml_url)

app.exec_()
UI非常简单:它只包含3个按钮,用于向状态机提交事件(
UI.qml
file):

状态机
stateMachine.scxml
由3种状态组成:
s1
s2
s3
和转换
t1
t2
t3

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early" xmlns:qt="http://www.qt.io/2015/02/scxml-ext" name="stateMachine" initial="s1">
    <state id="s1">
        <transition type="external" event="t1" target="s2"/>
        <onentry>
            <log label="entered" expr="s1"/>
        </onentry>
    </state>
    <state id="s2">
        <transition type="external" event="t2" target="s3"/>
        <onentry>
            <log label="entered" expr="s2"/>
        </onentry>
    </state>
    <state id="s3">
        <transition type="external" event="t3" target="s1">
        </transition>
        <onentry>
            <log label="entered" expr="s3"/>
        </onentry>
    </state>
</scxml>
不知何故,方法名称中的第一个字母被忽略了。我做错什么了吗?我对Qt和PySide2非常陌生。总体而言,这是一个好方法吗?我使用的是PySide2 5.11.1a1.dev1530708810518

您必须使用
SLOT()
将方法作为字符串传递(请记住
SLOT
SLOT
装饰器不同)


SLOT
仅在SLOT的名称前加前缀
1
,而SIGNAL对
2
也会加前缀,因此如果不想使用它,只需加前缀1:
(…,后端,“1ev_SLOT()”
,(我不建议这样做,因为它会降低代码的可读性)

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early" xmlns:qt="http://www.qt.io/2015/02/scxml-ext" name="stateMachine" initial="s1">
    <state id="s1">
        <transition type="external" event="t1" target="s2"/>
        <onentry>
            <log label="entered" expr="s1"/>
        </onentry>
    </state>
    <state id="s2">
        <transition type="external" event="t2" target="s3"/>
        <onentry>
            <log label="entered" expr="s2"/>
        </onentry>
    </state>
    <state id="s3">
        <transition type="external" event="t3" target="s1">
        </transition>
        <onentry>
            <log label="entered" expr="s3"/>
        </onentry>
    </state>
</scxml>
QObject::connect: No such slot BackEnd::v_slot()
from PySide2 import QtCore, QtGui, QtQml, QtScxml


class BackEnd(QtCore.QObject):
    @QtCore.Slot()
    def ev_slot(self):
        '''method called on event t1'''
        print('event t1')

    @QtCore.Slot(bool)
    def st_slot(self, active):
        '''method called on entering and exiting state s2'''
        if active:
            print('s2 entered')
        else:
            print('s2 exited')


if __name__ == '__main__':
    import sys
    app = QtGui.QGuiApplication(sys.argv)
    qml_url = QtCore.QUrl.fromLocalFile("ui.qml")

    # loading state machine
    my_state_machine = QtScxml.QScxmlStateMachine.fromFile('stateMachine.scxml')

    backend = BackEnd()
    conn1 = my_state_machine.connectToEvent("t1", backend, QtCore.SLOT("ev_slot()"))
    conn2 = my_state_machine.connectToState("s2", backend, QtCore.SLOT("st_slot(bool)"))
    my_state_machine.start()

    engine = QtQml.QQmlApplicationEngine()
    engine.rootContext().setContextProperty("stateMachine", my_state_machine)
    engine.load(qml_url)

    if not engine.rootObjects():
        sys.exit(-1)

    sys.exit(app.exec_())