乒乓状态

乒乓状态示例展示了如何使用Qt状态机框架中并行状态配合自定义事件和转换。

本示例实现了一个状态图,其中两个状态通过向状态机发布事件进行通信。状态图的表示如下。

pingerponger 状态是并行状态,即它们同时进入,并且将独立于对方进行转换。

当进入 pinger 状态时,将发布第一个 ping 事件;ponger 状态将通过发布一个 pong 事件进行响应;这会导致 pinger 状态发布一个新的 ping 事件;依此类推。

class PingEvent : public QEvent
{
public:
    PingEvent() : QEvent(PingEventType) { }
};

class PongEvent : public QEvent
{
public:
    PongEvent() : QEvent(PongEventType) { }
};

定义了两个自定义事件,PingEventPongEvent

class Pinger : public QState
{
public:
    explicit Pinger(QState *parent) : QState(parent) { }

protected:
    void onEntry(QEvent *) override
    {
        machine()->postEvent(new PingEvent);
        qInfo() << "ping?";
    }
};

Pinger 类定义了一个当进入状态时向状态机发布 PingEvent 的状态。

class PingTransition : public QAbstractTransition
{
public:
    PingTransition() {}

protected:
    bool eventTest(QEvent *e) override { return e->type() == PingEventType; }

    void onTransition(QEvent *) override
    {
        machine()->postDelayedEvent(new PongEvent, 500);
        qInfo() << "pong!";
    }
};

PingTransition 类定义了一个由类型为 PingEvent 的事件触发的转换,当转换被触发时,将向状态机发布一个 PongEvent(延迟500毫秒)。

class PongTransition : public QAbstractTransition
{
public:
    PongTransition() {}

protected:
    bool eventTest(QEvent *e) override { return (e->type() == PingEventType); }

    void onTransition(QEvent *) override
    {
        machine()->postDelayedEvent(new PingEvent, 500);
        qInfo() << "ping?";
    }
};

PongTransition 类定义了一个由类型为 PongEvent 的事件触发的转换,当转换被触发时,将向状态机发布一个 PingEvent(延迟500毫秒)。

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    QStateMachine machine;
    auto group = new QState(QState::ParallelStates);
    group->setObjectName("group");

main() 函数首先创建一个状态机和并行状态组。

    auto pinger = new Pinger(group);
    pinger->setObjectName("pinger");
    pinger->addTransition(new PongTransition);

    auto ponger = new QState(group);
    ponger->setObjectName("ponger");
    ponger->addTransition(new PingTransition);

接下来,创建了 pingerponger 状态,将并行状态组作为它们的父状态。请注意,转换是 无目标 的。当这样的转换被触发时,源状态不会被退出和重新进入;只有转换的 onTransition() 函数会被调用,状态机的配置将保持不变,这正是我们想要的。

    machine.addState(group);
    machine.setInitialState(group);
    machine.start();

    return app.exec();
}

最后,将组添加到状态机中,启动状态机,并进入应用程序事件循环。

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。包含在此处的文档贡献是各自拥有者的版权。本提供的文档是根据免费软件基金会发布的 GNU自由文档许可证版本1.3 的条款许可的。Qt和相应标志是芬兰和/或全球其他国家的The Qt Company Ltd.的商标。所有其他商标均是各自所有者的财产。