Auf dieser Seite

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.

Ampel mit grünem Licht und Pausentaste

Die Anwendung besteht aus drei Hauptkomponenten:

  • Einem TrafficLight Widget, das den aktuellen Zustand anzeigt.
  • Ein TaskTree Rezept, 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:

MethodeZweck
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::smashed her. 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 switchLightsTask Aufgaben ("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.

Beispielprojekt @ code.qt.io

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