TaskTree Ampel
Zeigt, wie man das Verhalten von Zustandsautomaten mit TaskTree durch eine Ampelsimulation implementiert.
Der TaskTree Traffic Light ist eine alternative Implementierung für die Traffic Light Beispiele in Qt SCXML und Qt State Machine.

Die Anwendung besteht aus drei Hauptkomponenten:
- Einem
TrafficLightWidget, das den aktuellen Zustand anzeigt. - Ein
TaskTreeRezept, das die Zustandsübergänge steuert. - Ein
GlueInterface, das die Benutzeroberfläche mit dem Zustandsautomaten synchronisiert.
Die folgenden Abschnitte beschreiben weitere Details des Beispielcodes.
Hilfsklasse Glue
Die Klasse GlueInterface sorgt für eine saubere Trennung zwischen der Benutzeroberfläche und der Betriebslogik.
enum class Light { Off = 0, Red = 1 << 0, Yellow = 1 << 1, Green = 1 << 2, }; Q_DECLARE_FLAGS(Lights, Light) Q_DECLARE_OPERATORS_FOR_FLAGS(Lights) class GlueInterface final : public QObject { Q_OBJECT public: // operational logic -> GUI void setLights(Lights lights) { emit lightsChanged(lights); } // GUI -> operational logic void smash() { emit smashed(); } void repair() { emit repaired(); } signals: void lightsChanged(Lights lights); void smashed(); void repaired(); };
Die Klasse GlueInterface bietet die folgenden Schnittstellenmethoden:
| Methode | Zweck |
|---|---|
setLights() | Aktualisiert den Ampelzustand aus dem TaskTree-Rezept |
lightsChanged() | Benachrichtigt die Benutzeroberfläche, wenn sich der Ampelzustand ändert |
smash()/ repair() | Behandelt Fehlersimulation und Wiederherstellungsaktionen |
Wenn Benutzer mit der Benutzeroberfläche interagieren:
- Durch Anklicken von Pause wird
smash()ausgelöst, um einen Fehler zu simulieren. - Durch Anklicken von Play wird
repair()ausgelöst und der normale Betrieb wiederhergestellt.
Implementierung des Zustandsautomaten
Die Logik des Zustandsautomaten wird durch ein TaskTree-Rezept implementiert. Die Methode recipe() erstellt diese Logik unter Verwendung eines Verweises auf GlueInterface:
ExecutableItem recipe(GlueInterface &iface) { return Forever { Group { // "working" state stopOnSuccess, parallel, signalAwaiterTask(&iface, &GlueInterface::smashed), // transitions to the "broken" state Forever { switchLightsTask(&iface, Light::Red, 3s), // "red" state switchLightsTask(&iface, Light::Red | Light::Yellow, 1s), // "redGoingGreen" state switchLightsTask(&iface, Light::Green, 3s), // "green" state switchLightsTask(&iface, Light::Yellow, 1s), // "greenGoingRed" state } }, Group { // "broken" state stopOnSuccess, parallel, signalAwaiterTask(&iface, &GlueInterface::repaired), // transitions to the "working" state Forever { switchLightsTask(&iface, Light::Yellow, 1s), // "blinking" state switchLightsTask(&iface, Light::Off, 1s), // "unblinking" state } } }; }
Verwaltung des Wurzelzustands
Das Element der obersten Ebene Forever führt seine Kinder in einer Endlosschleife aus. Es enthält zwei Untergruppen, die Arbeits- und Fehlerzustände darstellen.
Zustandsübergangsregeln:
- Die Zustände werden der Reihe nach ausgeführt, da die Voreinstellung execution mode sequential ist.
- Wenn ein Zustand abgeschlossen ist, beginnt der andere.
- Die Übergänge werden ausgelöst, wenn ein Benutzer auf der Benutzeroberfläche auf die Schaltfläche "Pause" oder "Abspielen" klickt, wodurch das entsprechende Signal ausgelöst wird.
Der "funktionierende" Betriebszustand
Der Arbeitszustand Group besteht aus zwei Tasks, die in parallel laufen:
- Die signalAwaiterTask stellt eine Verbindung zum Signal
GlueInterface::smashedher. Wenn das Signal ausgelöst wird, wird die Aufgabe sofort mit DoneResult::Success beendet. Dies führt dazu, dass die Arbeitsaufgabe Group nicht mehr ausgeführt wird, und das Rezept geht in den Zustand " unterbrochen" über. - Die verschachtelte Forever Aufgabe besteht aus vier
switchLightsTaskAufgaben ("red", "redGoingGreen", "green" und "greenGoingRed"), die sequentially in einer Endlosschleife ausgeführt werden.
Das Element stopOnSuccess jeder Gruppe weist sie an, die Ausführung zu beenden, wenn eine ihrer untergeordneten Aufgaben mit DoneResult::Success endet.
Die switchLightsTask Implementierung:
- Aktualisiert Lichtzustände durch
GlueInterface::setLights(). - Erzeugt eine zeitliche Verzögerung durch timeoutTask.
- Hält den Zustand für die angegebene Dauer aufrecht
timeout.
static Group switchLightsTask(GlueInterface *iface, Lights lights, const milliseconds &timeout) { return { onGroupSetup([iface, lights] { iface->setLights(lights); }), timeoutTask(timeout, DoneResult::Success) }; }
Der "unterbrochene" Betriebszustand
Der kaputte Zustand Group ist ähnlich wie der funktionierende Zustand Group. Der einzige Unterschied besteht darin, dass er mit dem Signal GlueInterface::repaired verbunden ist und die Lichter nur zwischen 2 Zuständen wechseln, wobei das gelbe Licht ein- und ausgeschaltet wird.
Einrichtung der Anwendung
Das Hauptanwendungssetup erstellt und verbindet alle Komponenten:
int main(int argc, char **argv) { QApplication app(argc, argv); GlueInterface iface; QTaskTree taskTree({recipe(iface)}); TrafficLight widget(iface); widget.show(); taskTree.start(); return app.exec(); }
Die Funktion main() instanziiert die Objekte QApplication, GlueInterface, QTaskTree und TrafficLight.
Um das taskTree Objekt zu erstellen, übergeben wir ein recipe(), das mit dem iface Objekt erstellt wurde. Die Funktion widget verwendet ebenfalls das übergebene iface Objekt.
Bevor die Anwendung ausgeführt wird, zeigt die Funktion main() das Widget TrafficLight an und startet den Aufgabenbaum.
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorauszuführen, öffnen Sie den Modus Welcome und wählen Sie das Beispiel aus Examples aus. Weitere Informationen finden Sie unter Qt Creator: Tutorial: Erstellen und Ausführen.
© 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.