TaskTree : feux de signalisation
Illustre comment implémenter le comportement d'une machine à états à l'aide de TaskTree à travers une simulation de feux tricolores.
Le feu tricolore TaskTree est une implémentation alternative des exemples de feux tricolores présentés dans Qt SCXML et Qt State Machine.

L'application se compose de trois éléments principaux :
- Un widget «
TrafficLight» qui affiche l'état actuel. - Une recette d’
TaskTreequi contrôle les transitions d’état. - Un
GlueInterfacequi synchronise l’interface utilisateur avec la machine à états.
Les sections suivantes décrivent plus en détail le code de l’exemple.
Classe d'aide « Glue »
La classe d’ GlueInterface permet une séparation claire entre l’interface utilisateur et la logique opérationnelle.
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();
};La classe d'GlueInterface fournit les méthodes d'interface suivantes :
| Méthode | Objectif |
|---|---|
setLights() | Met à jour l'état du feu tricolore à partir de la recette TaskTree |
lightsChanged() | Informe l'interface utilisateur lorsque l'état des feux change |
smash()/ repair() | Gère la simulation de défaillance et les actions de reprise |
Lorsque les utilisateurs interagissent avec l'interface utilisateur :
- Cliquer sur « Pause » déclenche
smash(), simulant ainsi un dysfonctionnement. - Cliquer sur « Lecture » déclenche
repair(), rétablissant ainsi le fonctionnement normal.
Implémentation de la machine à états
La logique de la machine à états est implémentée via une recette TaskTree. La méthode ` recipe() ` crée cette logique en utilisant une référence à ` 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
}
}
};
}Gestion de l’état racine
L'élément Forever de niveau supérieur exécute ses enfants dans une boucle infinie. Il contient deux sous-groupes représentant les états « fonctionnel » et « défaillant ».
Règles de transition d’états :
- Les états s’exécutent dans l’ordre, car l’ execution mode par défaut est sequential.
- Lorsqu’un état se termine, l’autre commence.
- Les transitions sont déclenchées lorsqu'un utilisateur clique sur le bouton « Pause » ou « Lecture » de l'interface utilisateur, ce qui émet le signal correspondant.
L’état de fonctionnement « working »
L’ Group « working » se compose de deux tâches s’exécutant dans l’état « parallel » :
- L’ signalAwaiterTask se connecte au signal «
GlueInterface::smashed». Si le signal est déclenché, la tâche se termine immédiatement avec « DoneResult::Success ». Cela provoque l’arrêt de l’exécution de l’ Group « working », et la recette passe à l’état « broken ». - La tâche imbriquée « Forever » se compose de quatre tâches «
switchLightsTask» (« red », « redGoingGreen », « green » et « greenGoingRed ») exécutées sequentially dans une boucle infinie.
L’élément « stopOnSuccess » de chaque groupe lui ordonne d’arrêter son exécution dès qu’une de ses tâches enfants se termine par « DoneResult::Success ».
Implémentation de ` switchLightsTask ` :
- Mise à jour des états d’éclairage via `
GlueInterface::setLights()`. - Crée un délai temporisé à l’aide de ` timeoutTask`.
- Conserve l’état pendant la durée spécifiée à l’aide de `
timeout`.
static Group switchLightsTask(GlueInterface *iface, Lights lights, const milliseconds &timeout)
{
return {
onGroupSetup([iface, lights] { iface->setLights(lights); }),
timeoutTask(timeout, DoneResult::Success)
};
}L'état de fonctionnement « défectueux »
L’ Group « broken » est similaire à l’ Group« working ». La seule différence réside dans le fait qu’elle se connecte au signal « GlueInterface::repaired », et que les lumières basculent uniquement entre deux états, allumant et éteignant la lumière jaune.
Configuration de l’application
La configuration principale de l’application crée et connecte tous les composants :
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();
}La fonction ` main() ` instancie les objets `QApplication`, ` GlueInterface`, `QTaskTree` et ` TrafficLight `.
Pour construire l’objet ` taskTree `, nous lui transmettons un objet ` recipe() ` construit à partir de l’objet ` iface `. L’objet ` widget ` utilise également l’objet ` iface ` qui lui a été transmis.
Avant d’exécuter l’application, la fonction main() affiche le widget TrafficLight et lance l’arborescence des tâches.
Exécution de l’exemple
Vous pouvez exécuter l’exemple à partir de :
- Qt Creator
Ouvrez le mode « Welcome » et sélectionnez l’exemple dans « Examples ». Pour plus d’informations, consultez Qt Creator: Tutoriel : Compiler et exécuter.
- Qt Extension for Visual Studio Code
Exécutez la commande « Qt: Open Qt examples » à partir de Command Palette, puis sélectionnez l’exemple dans la liste. Pour plus d’informations, consultez Qt Extension for Visual Studio Code: Tutoriel : Compiler et exécuter.
© 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.