Python PySide2中QScxmlStateMachine.connectToEvent的奇怪行为
我正在尝试编写一个桌面应用程序,在后端使用Python,在前端使用QML,并使用scxml创建状态机。我正在使用PySide2。我的意图是通过状态机描述应用程序的逻辑。根据状态,QML中的UI应该做出相应的反应。此外,后端应根据输入的状态等执行方法 我的项目由3个文件组成: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
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_())