Auf dieser Seite

TaskTree-Demo

Zeigt, wie sich verschiedene Ausführungsmodi und Workflow-Richtlinien auf die komplexe TaskTree-Ausführung auswirken.

Die TaskTree-Demo zeigt, wie ein verschachteltes TaskTree-Rezept unter Verwendung von timeoutTask aufgebaut wird, und demonstriert verschiedene execution modes und workflow policies. Die Anwendung bietet einen grafischen Überblick über den Fortschritt, während der TaskTree die verschiedenen Arbeitselemente ausführt, aus denen die Aufgabe besteht.

Verschachtelte Aufgabengruppen mit farbcodierten Zuständen, die den Fortschritt bei 78 Prozent anzeigen

Die Demoanwendung verwendet ein einziges QWidget, um eine TaskTree-Hierarchie anzuzeigen und zu verwalten. Die Schnittstelle sieht folgendermaßen aus:

  • Aufgaben erscheinen als Blattknoten auf der rechten Seite des Baums.

    Für jede Aufgabe können Sie die Ausführungsdauer festlegen und den Status der erfolgreichen oder fehlerhaften Ausführung konfigurieren.

  • Gruppenknoten erscheinen auf der linken und mittleren Seite des Baums.

    Jede Gruppe kann mehrere untergeordnete Aufgaben oder verschachtelte Gruppen enthalten. Sie können execution modes und workflow policies für jede Gruppe konfigurieren.

  • Farbindikatoren zeigen den aktuellen Ausführungsstatus jedes Knotens an.

In den folgenden Abschnitten werden weitere Details des Beispielcodes beschrieben.

Helper Glue-Klassen

Die abstrakte Klasse GlueItem verbindet die Komponenten der Benutzeroberfläche (UI) mit ihren entsprechenden TaskTree-Rezepten. Dieses Entwurfsmuster ermöglicht eine saubere Trennung zwischen der Benutzeroberfläche und der Aufgabenlogik.

class GlueItem
{
public:
    virtual ExecutableItem recipe() const = 0;
    virtual QWidget *widget() const = 0;
    virtual void reset() const = 0;

    virtual ~GlueItem() = default;
};

Die Klasse GlueItem definiert drei wichtige virtuelle Methoden:

MethodeZweck
recipe()Erstellt und gibt ein TaskTree-Rezept zurück, das das Verhalten des Elements definiert
widget()Ermöglicht den Zugriff auf die zugehörige UI-Komponente
reset()Versetzt die UI-Komponente in ihren Ausgangszustand zurück

Die Klasse GroupGlueItem verwaltet Group Elemente in Ihrer Aufgabenhierarchie. Jede Gruppe kann andere GlueItem Elemente als Kinder enthalten, einschließlich verschachtelter GroupGlueItems oder TaskGlueItems.

Im Folgenden wird beschrieben, wie die Methode recipe() eine Gruppe erstellt und konfiguriert:

ExecutableItem GroupGlueItem::recipe() const
{
    GroupItems childRecipes;
    for (GlueItem *child : m_children)
        childRecipes.append(child->recipe());

    return Group {
        m_groupWidget->executeModeItem(),
        m_groupWidget->workflowPolicyItem(),
        onGroupSetup([this] { m_groupWidget->setState(State::Running); }),
        childRecipes,
        onGroupDone([this](DoneWith result) { m_groupWidget->setState(resultToState(result)); })
    };
}

Schlüsselkomponenten der Implementierung:

  • Erzeugt ein neues Group mit untergeordneten Rezepten
  • Wendet execution mode und workflow policy aus den UI-Einstellungen an
  • Verwendung von onGroupSetup() zur Aktualisierung der Benutzeroberfläche bei Beginn der Ausführung
  • Verwendet onGroupDone(), um Ausführungsergebnisse in der Benutzeroberfläche wiederzugeben

Die Klasse TaskGlueItem implementiert Blattknoten in Ihrem Aufgabenbaum mit timeoutTask.

Hier ist die recipe() Implementierung, die die Aufgabe erstellt:

ExecutableItem TaskGlueItem::recipe() const
{
    return Group {
        onGroupSetup([this] { m_taskWidget->setState(State::Running); }),
        timeoutTask(seconds(m_taskWidget->busyTime()), m_taskWidget->desiredResult()),
        onGroupDone([this](DoneWith result) { m_taskWidget->setState(resultToState(result)); })
    };
}

Die Implementierung:

  • Erzeugt eine Group, die einen Task umhüllt. timeoutTask
  • Verwendet UI-Einstellungen, um Dauer und erwartetes Ergebnis zu konfigurieren
  • Aktualisiert den UI-Status bei Beginn der Aufgabe über onGroupSetup()
  • Reflektiert den Status der Aufgabenbeendigung über onGroupDone()

Aufbau der Aufgabenhierarchie

Zwei Hilfsmethoden vereinfachen die Erstellung von Aufgabenbäumen:

static GlueItem *group(const GroupSetup &groupSetup, const QList<GlueItem *> children)
{
    return new GroupGlueItem(groupSetup, children);
}

static GlueItem *task(int busyTime = 1, DoneResult result = DoneResult::Success)
{
    return new TaskGlueItem(busyTime, result);
}
  • group(): Erzeugt einen neuen GroupGlueItem
  • task(): Erzeugt einen neuen TaskGlueItem

Definieren der Baumstruktur

Der folgende Code zeigt, wie Sie eine vollständige Aufgabenhierarchie aufbauen können:

    std::unique_ptr<GlueItem> tree {
        group({WorkflowPolicy::ContinueOnSuccess}, {
            group({}, {
                task(),
                task(2, DoneResult::Error),
                task(3)
            }),
            task(),
            task(),
            group({WorkflowPolicy::FinishAllAndSuccess}, {
                task(),
                task(),
                group({WorkflowPolicy::StopOnError, ExecuteMode::Parallel}, {
                    task(4),
                    task(2),
                    task(1),
                    task(3, DoneResult::Error)
                }),
                task(2),
                task(3)
            }),
            task()
        })
    };

Sie können das obige Konstrukt abändern, um verschiedene Baumstrukturen zu erstellen.

Verbinden der Benutzeroberfläche mit TaskTree

Der letzte Schritt verbindet den TaskTree mit den UI-Steuerelementen der Anwendung:

    QSingleTaskTreeRunner taskTreeRunner;

    const auto resetTaskTree = [&] {
        taskTreeRunner.reset();
        tree->reset();
        progressBar->setValue(0);
        cancelButton->setEnabled(false);
    };

    const auto cancelTaskTree = [&] { taskTreeRunner.cancel(); };

    const auto startTaskTree = [&] {
        resetTaskTree();
        cancelButton->setEnabled(true);

        const auto onTaskTreeSetup = [progressBar](QTaskTree &taskTree) {
            progressBar->setMaximum(taskTree.progressMaximum());
            QObject::connect(&taskTree, &QTaskTree::progressValueChanged,
                             progressBar, &QProgressBar::setValue);
        };

        const auto onTaskTreeDone = [cancelButton] { cancelButton->setEnabled(false); };

        taskTreeRunner.start({tree->recipe()}, onTaskTreeSetup, onTaskTreeDone);
    };

    QObject::connect(startButton, &QAbstractButton::clicked, &app, startTaskTree);
    QObject::connect(cancelButton, &QAbstractButton::clicked, &app, cancelTaskTree);
    QObject::connect(resetButton, &QAbstractButton::clicked, &app, resetTaskTree);

    mainWidget.show();

    return app.exec();

Dieser Code:

  • Erzeugt einen QSingleTaskTreeRunner zur Ausführung des TaskTrees
  • Richtet Handler für die Schaltflächen Start, Abbrechen und Zurücksetzen ein
  • Verbindet den Fortschrittsbalken, um die Ausführung der Aufgabe zu verfolgen

Ausführen des Beispiels

Um das Beispiel auszuführen 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.