Semáforo TaskTree
Demuestra cómo implementar el comportamiento de una máquina de estados utilizando TaskTree a través de la simulación de un semáforo.
El Semáforo de TaskTree es una implementación alternativa para los ejemplos de Semáforo en Qt SCXML y Qt State Machine.

La aplicación consta de tres componentes principales:
- Un widget
TrafficLightque muestra el estado actual. - Una receta
TaskTreeque controla las transiciones de estado. - Un
GlueInterfaceque sincroniza la interfaz de usuario con la máquina de estados.
Las siguientes secciones describen más detalles del código del ejemplo.
Clase Helper Glue
La clase GlueInterface proporciona una separación limpia entre la interfaz de usuario y la lógica operativa.
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 clase GlueInterface proporciona los siguientes métodos de interfaz:
| Método | Propósito |
|---|---|
setLights() | Actualiza el estado del semáforo desde la receta TaskTree |
lightsChanged() | Notifica a la interfaz de usuario los cambios de estado de los semáforos |
smash()/ repair() | Gestiona la simulación de fallos y las acciones de recuperación |
Cuando los usuarios interactúan con la interfaz de usuario:
- Al hacer clic en pausa, se activa
smash(), simulando un fallo. - Al hacer clic en reproducir se activa
repair(), restableciendo el funcionamiento normal.
Implementación de la máquina de estados
La lógica de la máquina de estados se implementa a través de una receta TaskTree. El método recipe() crea esta lógica utilizando una referencia a 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 } } }; }
Gestión del estado raíz
El elemento de nivel superior Forever ejecuta a sus hijos en un bucle infinito. Contiene dos subgrupos que representan estados de trabajo y estados rotos.
Reglas de transición de los estados:
- Los estados se ejecutan en secuencia, ya que por defecto execution mode es sequential.
- Cuando un estado finaliza, comienza el otro.
- Las transiciones se activan cuando un usuario pulsa el botón de pausa o reproducción en la interfaz de usuario, emitiendo la señal correspondiente.
El estado de funcionamiento "de trabajo
El estado de funcionamiento Group consta de dos tareas que se ejecutan en parallel:
- La signalAwaiterTask se conecta a la señal
GlueInterface::smashed. Si la señal se activa, la tarea termina inmediatamente con DoneResult::Success. Esto provoca que la tarea Group deje de ejecutarse, y la receta pasa al estado roto. - La tarea anidada Forever consiste en cuatro tareas
switchLightsTask("red", "redGoingGreen", "green", y "greenGoingRed") ejecutadas sequentially en un bucle infinito.
El elemento stopOnSuccess de cada grupo le indica que deje de ejecutarse cuando cualquiera de sus tareas hijas termine con DoneResult::Success.
La implementación de switchLightsTask:
- Actualiza los estados de las luces mediante
GlueInterface::setLights(). - Crea un retardo temporizado mediante timeoutTask.
- Mantiene el estado durante la duración especificada
timeout.
static Group switchLightsTask(GlueInterface *iface, Lights lights, const milliseconds &timeout) { return { onGroupSetup([iface, lights] { iface->setLights(lights); }), timeoutTask(timeout, DoneResult::Success) }; }
El estado de operación "roto
El estado roto Group es similar al estado de funcionamiento Group. La única diferencia es que se conecta a la señal GlueInterface::repaired, y las luces ciclan sólo entre 2 estados encendiendo y apagando la luz amarilla.
Configuración de la aplicación
La configuración principal de la aplicación crea y conecta todos los componentes:
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 función main() instanciará los objetos QApplication, GlueInterface, QTaskTree y TrafficLight.
Para construir el objeto taskTree, pasamos un recipe() construido con el objeto iface. El widget también utiliza el objeto iface pasado.
Antes de ejecutar la aplicación, la función main() muestra el widget TrafficLight e inicia el árbol de tareas.
Ejecutar el ejemplo
Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.
© 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.