状态机的实例化
无论是动态创建的还是编译生成的状态机,其行为方式、属性、状态、数据模型等均完全一致。它们唯一的区别仅在于实例化方式。若要在 C++ 中根据 SCXML 文件动态创建状态机,可使用以下代码:
auto *stateMachine = QScxmlStateMachine::fromFile("MyStatemachine.scxml");或者,在 QML 中:
import QtScxml
Item {
property StateMachine stateMachine: scxmlLoader.stateMachine
StateMachineLoader {
id: scxmlLoader
source: "statemachine.scxml"
}
}编译后的状态机可以像任何 C++ 对象一样进行实例化:
auto *stateMachine = new MyStatemachine;或者:
MyStatemachine stateMachine;要在 QML 中使用已编译的状态机,可以将其注册为 QML 类型:
struct MyStateMachineRegistration {
Q_GADGET
QML_NAMED_ELEMENT(MyStateMachine)
QML_FOREIGN(MyStateMachine)
QML_ADDED_IN_VERSION(1, 0)
};然后,你可以在 QML 中像这样实例化它:
import MyStateMachine 1.0
MyStateMachine {
id: stateMachine
}要编译状态机,必须在项目的构建文件中添加以下几行代码:
使用 cmake 时:
find_package(Qt6 REQUIRED COMPONENTS Scxml)
target_link_libraries(mytarget PRIVATE Qt6::Scxml)qt_add_statecharts(mytarget
MyStatemachine.scxml
)使用 qmake 时:
QT += scxmlSTATECHARTS = MyStatemachine.scxml这将指示 qmake 运行qscxmlc,该工具会生成 MyStatemachine.h 和 MyStatemachine.cpp,并将它们添加到项目的头文件和源文件中。默认情况下,生成的文件保存在构建目录中。 可以设置 qmake 的QSCXMLC_DIR或 cmake 的OUTPUT_DIRECTORY变量来指定另一个目录。可以设置 qmake 的QSCXMLC_NAMESPACE或 cmake 的NAMESPACE变量,将状态机代码放入 C++ 命名空间中。
实例化状态机后,您可以按如下方式连接到任何状态的“active”属性。例如,如果交通信号灯的状态机有一个表示红灯的状态(在 scxml 文件中,该状态的 ID 为“red”),您可以编写:
stateMachine->connectToState("red", [](boolactive) {
qDebug() << (active ? "entered" : "exited") << "the red state";
});而在 QML 中:
Light {
id: greenLight
color: "green"
visible: stateMachine.green
}若想在状态机发出事件时收到通知,可将其与相应的信号连接。例如,对于一个通过发送事件来指示播放已停止的媒体播放器状态机,可以这样编写:
stateMachine->connectToEvent("playbackStopped", [](constQScxmlEvent&){
qDebug() << "Stopped!";
});而在 QML 中:
import QtScxml
EventConnection {
stateMachine: stateMachine
events: ["playbackStopped"]
onOccurred: console.log("Stopped!")
}向状态机发送事件同样简单:
stateMachine->submitEvent("tap", QVariantMap({
{ "artist", "Fatboy Slim" },
{ "title", "The Rockafeller Skank" }
}));这将生成一个“tap”事件,地图内容可在状态机内的 _event.data 中获取。在 QML 中:
stateMachine.submitEvent("tap", {
"artist": "Fatboy Slim"
"title": "The Rockafeller Skank"
})注意:状态机 需要QEventLoop 才能正常工作。事件循环用于实现事件的delay 属性,并在接收到来自嵌套(或父级)状态机的事件时安排状态机的处理。QML应用程序或小部件应用程序中始终会有一个正在运行的事件循环,因此无需额外操作。 对于其他应用程序,则需要调用QApplication::run 来启动事件循环处理。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.