Instanziierung von Zustandsautomaten

Sowohl die dynamisch erstellten als auch die kompilierten Zustandsautomaten verhalten sich gleich, haben die gleichen Eigenschaften, Zustände, Datenmodelle usw. Sie unterscheiden sich nur in der Art und Weise, wie sie instanziiert werden. Um einen Zustandsautomaten in C++ dynamisch aus einer SCXML-Datei zu erstellen, können Sie verwenden:

auto *stateMachine = QScxmlStateMachine::fromFile("MyStatemachine.scxml");

Oder, in QML:

import QtScxml

Item {
    property StateMachine stateMachine: scxmlLoader.stateMachine

    StateMachineLoader {
        id: scxmlLoader
        source: "statemachine.scxml"
    }
}

Ein kompilierter Zustandsautomat kann auf dieselbe Weise instanziiert werden wie jedes C++-Objekt:

auto *stateMachine = new MyStatemachine;

Oder:

MyStatemachine stateMachine;

Um einen kompilierten Zustandsautomaten in QML zu verwenden, können Sie ihn als QML-Typ registrieren:

struct MyStateMachineRegistration {
    Q_GADGET
    QML_NAMED_ELEMENT(MyStateMachine)
    QML_FOREIGN(MyStateMachine)
    QML_ADDED_IN_VERSION(1, 0)
};

Dann können Sie ihn in QML instanziieren, etwa so:

import MyStateMachine 1.0

MyStateMachine {
    id: stateMachine
}

Um einen Zustandsautomaten zu kompilieren, müssen die folgenden Zeilen in die Build-Datei des Projekts eingefügt werden:

Bei Verwendung von cmake:

find_package(Qt6 REQUIRED COMPONENTS Scxml)
target_link_libraries(mytarget PRIVATE Qt6::Scxml)
qt_add_statecharts(mytarget
    MyStatemachine.scxml
)

Bei Verwendung von qmake:

QT += scxml
STATECHARTS = MyStatemachine.scxml

Dies weist qmake an, qscxmlc auszuführen, das MyStatemachine.h und MyStatemachine.cpp generiert und sie entsprechend zu den Projekt-Headern und -Sourcen hinzufügt. Standardmäßig werden die generierten Dateien im Build-Verzeichnis gespeichert. Die Variablen qmake QSCXMLC_DIR oder cmake OUTPUT_DIRECTORY können gesetzt werden, um ein anderes Verzeichnis anzugeben. Die Variable qmake QSCXMLC_NAMESPACE oder cmake NAMESPACE kann gesetzt werden, um den Zustandsmaschinencode in einen C++-Namensraum zu legen.

Nach der Instanziierung eines Zustandsautomaten können Sie wie folgt eine Verbindung zur aktiven Eigenschaft eines beliebigen Zustands herstellen. Wenn zum Beispiel der Zustandsautomat für eine Ampel einen Zustand hat, der anzeigt, dass die Ampel rot ist (mit der praktischen ID "red" in der scxml-Datei), können Sie schreiben:

stateMachine->connectToState("red", [](bool active) {    qDebug() << (active ? "entered" : "exited") << "the red state";
});

Und in QML:

Light {
    id: greenLight
    color: "green"
    visible: stateMachine.green
}

Wenn Sie benachrichtigt werden möchten, wenn ein Zustandsautomat ein Ereignis sendet, können Sie sich mit dem entsprechenden Signal verbinden. Zum Beispiel können Sie für einen Medienplayer-Zustandsautomaten, der durch Senden eines Ereignisses anzeigt, dass die Wiedergabe gestoppt wurde, schreiben:

stateMachine->connectToEvent("playbackStopped", [](const QScxmlEvent &){    qDebug() << "Stopped!";
});

Und in QML:

import QtScxml

EventConnection {
    stateMachine: stateMachine
    events: ["playbackStopped"]
    onOccurred: console.log("Stopped!")
}

Das Senden von Ereignissen an einen Zustandsautomaten ist ebenso einfach:

stateMachine->submitEvent("tap", QVariantMap({
    { "artist", "Fatboy Slim" },
    { "title", "The Rockafeller Skank" }
}));

Es wird ein "Tap"-Ereignis mit dem Karteninhalt erzeugt, der in _event.data innerhalb des Zustandsautomaten verfügbar ist. In QML:

stateMachine.submitEvent("tap", {
    "artist": "Fatboy Slim"
    "title": "The Rockafeller Skank"
})

Hinweis: Ein Zustandsautomat benötigt eine QEventLoop, um korrekt zu funktionieren. Die Ereignisschleife wird verwendet, um das delay -Attribut für Ereignisse zu implementieren und um die Verarbeitung eines Zustandsautomaten zu planen, wenn Ereignisse von verschachtelten (oder übergeordneten) Zustandsautomaten empfangen werden. In einer QML-Anwendung oder einer Widget-Anwendung wird immer eine Ereignisschleife laufen, so dass nichts Zusätzliches benötigt wird. Bei anderen Anwendungen muss QApplication::run aufgerufen werden, um die Verarbeitung der Ereignisschleife zu starten.

© 2025 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.