Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \page qtscxml-instantiating-state-machines.html
++ \title Instantiating State Machines
++ \brief Instantiating dynamically created and compiled state machines in C++
++ and QML
++
++ Both the dynamically created and the compiled state machines behave in the
++ same way, have the same properties, states, data model, and so on. They only
++ differ in the way they are instantiated. To dynamically create one in C++
++ from an SCXML file, you can use:
++
++ \code
++ auto *stateMachine = QScxmlStateMachine::fromFile("MyStatemachine.scxml");
++ \endcode
++
++ Or, in QML:
++
++ \qml
++ import QtScxml
++
++ Item {
++ property StateMachine stateMachine: scxmlLoader.stateMachine
++
++ StateMachineLoader {
++ id: scxmlLoader
++ source: "statemachine.scxml"
++ }
++ }
++ \endqml
++
++ A compiled state machine can be instantiated the same way as any C++
++ object:
++
++ \code
++ auto *stateMachine = new MyStatemachine;
++ \endcode
++
++ Or:
++
++ \code
++ MyStatemachine stateMachine;
++ \endcode
++
++ To use a compiled state machine in QML, you can register it as a QML type:
++
++ \code
++ struct MyStateMachineRegistration {
++ Q_GADGET
++ QML_NAMED_ELEMENT(MyStateMachine)
++ QML_FOREIGN(MyStateMachine)
++ QML_ADDED_IN_VERSION(1, 0)
++ };
++ \endcode
++
++ Then you can instantiate it in QML, like this:
++
++ \qml
++ import MyStateMachine 1.0
++
++ MyStateMachine {
++ id: stateMachine
++ }
++ \endqml
++
++ To compile a state machine, the following lines have to be added to the
++ project build file:
++
++ When using cmake:
++
++ \include qtscxml-module-use.qdocinc cmakebuild
++ \include qtscxml-module-use.qdocinc cmakestatecharts
++
++ When using qmake:
++
++ \include qtscxml-module-use.qdocinc qmakebuild
++ \include qtscxml-module-use.qdocinc qmakestatecharts
++
++ This will tell qmake to run \e qscxmlc which generates MyStatemachine.h
++ and MyStatemachine.cpp, and adds them to appropriately to the project
++ headers and sources. By default, the generated files are saved in
++ the build directory. The qmake \e QSCXMLC_DIR or cmake \e OUTPUT_DIRECTORY
++ variable can be set to specify another directory. The qmake
++ \e QSCXMLC_NAMESPACE or cmake \e NAMESPACE variable can be set to put the
++ state machine code into a C++ namespace.
++
++ After instantiating a state machine, you can connect to any state's
++ active property as follows. For example, if the state machine for a
++ traffic light has a state indicating that the light is red (which has the
++ convenient id "red" in the scxml file), you can write:
++
++ \code
++ stateMachine->connectToState("red", [](bool active) {
++ qDebug() << (active ? "entered" : "exited") << "the red state";
++ });
++ \endcode
++
++ And in QML:
++
++ \qml
++ Light {
++ id: greenLight
++ color: "green"
++ visible: stateMachine.green
++ }
++ \endqml
++
++ If you want to be notified when a state machine sends out an event, you
++ can connect to the corresponding signal. For example, for a media player
++ state machine which indicates that playback has stopped by sending an
++ event, you can write:
++
++ \code
++ stateMachine->connectToEvent("playbackStopped", [](const QScxmlEvent &){
++ qDebug() << "Stopped!";
++ });
++ \endcode
++
++ And in QML:
++
++ \qml
++ import QtScxml
++
++ EventConnection {
++ stateMachine: stateMachine
++ events: ["playbackStopped"]
++ onOccurred: console.log("Stopped!")
++ }
++ \endqml
++
++ Sending events to a state machine is equally simple:
++
++ \code
++ stateMachine->submitEvent("tap", QVariantMap({
++ { "artist", "Fatboy Slim" },
++ { "title", "The Rockafeller Skank" }
++ }));
++ \endcode
++
++ This will generate a "tap" event with the map contents available in
++ _event.data inside the state machine. In QML:
++
++ \code
++ stateMachine.submitEvent("tap", {
++ "artist": "Fatboy Slim"
++ "title": "The Rockafeller Skank"
++ })
++ \endcode
++
++ \note A state machine needs a \c QEventLoop to work correctly. The event loop is used
++ to implement the \c delay attribute for events and to schedule the processing of a state machine
++ when events are received from nested (or parent) state machines. A QML application or a widget
++ application will always have an event loop running, so nothing extra is needed. For other
++ applications, \c QApplication::run will have to be called to start the event loop processing.
++ */