Qt之QStateMachine等待
- IT业界
- 2025-09-21 03:15:02

在项目中经常需要等待,我们模拟0-30的数,假如我们其中5, 25的数需要进行等待,等待用户处理完自己事情后,按下按钮继续,找Qt的项目中有一个
QStateMachineqstatemmachine类提供了一个分层有限状态机。 QStateMachine基于Statecharts的概念和符号。qstatemmachine是状态机框架的一部分。 状态机管理一组状态(从QAbstractState继承的类)和这些状态之间的转换(QAbstractTransition的后代);这些状态和转换定义了一个状态图。一旦构建了状态图,状态机就可以执行它。qstatemmachine的执行算法基于状态图XML (SCXML)算法。该框架的概述给出了几个状态图和构建它们的代码。 使用addState()函数向状态机添加顶级状态。使用removeState()函数删除状态。不鼓励在机器运行时删除状态。 在机器启动之前,必须设置初始状态。初始状态是机器启动时进入的状态。然后可以启动状态机。当进入初始状态时,就会发出started()信号。 机器是事件驱动的,并保持自己的事件循环。事件通过postEvent()发送到机器。请注意,这意味着它是异步执行的,并且如果没有正在运行的事件循环,它将无法进行。你通常不需要将事件直接发布到机器上,因为Qt的转换,例如,QEventTransition和它的子类,会处理这个。但是对于由事件触发的自定义转换,postEvent()很有用。 状态机处理事件并进行转换,直到进入顶级最终状态;然后状态机发出finished()信号。您还可以显式地stop()状态机。在这种情况下,会发出stopped()信号。 下面的代码片段显示了一个状态机,当按钮被点击时,状态机将完成:
QPushButton button; QStateMachine machine; QState *s1 = new QState(); s1->assignProperty(&button, "text", "Click me"); QFinalState *s2 = new QFinalState(); s1->addTransition(&button, SIGNAL(clicked()), s2); machine.addState(s1); machine.addState(s2); machine.setInitialState(s1); machine.start();那么我们实现自己
Processor类 #ifndef PROCESSOR_H #define PROCESSOR_H #include <QObject> #include <QStateMachine> #include <QState> #include <QFinalState> class Processor : public QObject { Q_OBJECT public: explicit Processor(QObject *parent = nullptr); void startProcessing(); void resumeProcessing(); signals: void progressUpdated(int value); void runSig(); void paused(); void finished(); private: void processNextItem(); bool isRunning() const; private: QStateMachine *m_machine; QState *m_runningState; QState *m_pausedState; QFinalState *m_finishedState; int m_currentIndex; }; #endif // PROCESSOR_H #include "processor.h" #include <QDebug> #include <QTimer> #include <QThread> Processor::Processor(QObject *parent) : QObject(parent), m_machine(new QStateMachine(this)), m_runningState(new QState(m_machine)), m_pausedState(new QState(m_machine)), m_finishedState(new QFinalState(m_machine)), m_currentIndex(0) { // 配置运行状态 connect(m_runningState, &QState::entered, [this]() { qDebug() << "Entered running state"; processNextItem(); }); // 配置暂停状态 connect(m_pausedState, &QState::entered, [this]() { qDebug() << "Entered paused state"; }); // 配置暂停状态 // connect(m_finishedState, &QState::entered, [this]() { // qDebug() << "Entered finished state"; // }); // 配置状态转换 m_runningState->addTransition(this, &Processor::paused, m_pausedState); m_pausedState->addTransition(this, &Processor::runSig, m_runningState); m_runningState->addTransition(this, &Processor::finished, m_finishedState); // 配置状态机 m_machine->setInitialState(m_runningState); } bool Processor::isRunning() const { return m_machine->isRunning(); } void Processor::startProcessing() { if (!m_machine->isRunning()) { qDebug() << "Starting processing..."; m_machine->start(); } } void Processor::resumeProcessing() { ++m_currentIndex; emit runSig(); } void Processor::processNextItem() { if (m_currentIndex >= 30) { emit finished(); return; } emit progressUpdated(m_currentIndex); if (m_currentIndex == 5 || m_currentIndex == 25) { qDebug() << "--- Reached pause point ---"; emit paused(); } else { // 只有非暂停点时继续自动处理 m_currentIndex++; QThread::msleep(200); //模拟耗时操作 processNextItem(); } }单例模式
#ifndef TASKPROCESSOR_H #define TASKPROCESSOR_H #include <QObject> #include <QStateMachine> #include <QState> #include <QFinalState> #include <QQueue> #include <QMutex> #include <functional> class TaskProcessor : public QObject { Q_OBJECT public: // 单例接口,保证全局唯一 static TaskProcessor& getInstance() { static TaskProcessor processor; return processor; } // 添加任务到队列 void addTask(const std::function<void()>& task); // 开始处理任务队列 void startProcessing(); // 暂停任务处理(例如等待外部事件) void pauseProcessing(); // 恢复任务处理 void resumeProcessing(); signals: // 任务状态信号,可根据需求扩展 void pausedSig(); void resumeSig(); void taskStarted(); void taskFinished(); void allTasksFinished(); private: // 构造函数私有,确保单例 explicit TaskProcessor(QObject *parent = nullptr); Q_DISABLE_COPY(TaskProcessor) // 内部处理任务队列的方法 void processNextTask(); // 任务队列及同步保护 QQueue<std::function<void()>> m_taskQueue; QMutex m_mutex; // 状态机及状态 QStateMachine *m_machine; QState *m_runningState; QState *m_pausedState; QFinalState *m_finishedState; }; #endif // TASKPROCESSOR_H #include "processor.h" #include <QDebug> #include <QThread> TaskProcessor::TaskProcessor(QObject *parent) : QObject(parent), m_machine(new QStateMachine(this)), m_runningState(new QState(m_machine)), m_pausedState(new QState(m_machine)), m_finishedState(new QFinalState(m_machine)) { // 配置运行状态:进入运行状态时,尝试处理下一个任务 connect(m_runningState, &QState::entered, this, [this]() { qDebug() << "Entered running state"; processNextTask(); }); // 配置暂停状态:仅做记录,具体暂停逻辑可通过状态机外部控制 connect(m_pausedState, &QState::entered, this, [this]() { qDebug() << "Entered paused state"; }); // 状态切换配置:暂停和恢复 m_runningState->addTransition(this, SIGNAL(pausedSig()), m_pausedState); m_pausedState->addTransition(this, SIGNAL(resumeSig()), m_runningState); // 当任务全部处理完毕时,切换到结束状态 m_runningState->addTransition(this, SIGNAL(allTasksFinished()), m_finishedState); // 状态机初始状态设为运行状态 m_machine->setInitialState(m_runningState); } void TaskProcessor::addTask(const std::function<void()>& task) { QMutexLocker locker(&m_mutex); m_taskQueue.enqueue(task); } void TaskProcessor::startProcessing() { if (!m_machine->isRunning()) { qDebug() << "Starting Task Processing..."; m_machine->start(); } } void TaskProcessor::pauseProcessing() { // 可以发出信号通知状态机进入暂停状态 qDebug() << "Requesting pause..."; emit pausedSig(); // 此处 SIGNAL 与状态机转换绑定 } void TaskProcessor::resumeProcessing() { // 发出信号恢复处理 qDebug() << "Requesting resume..."; emit resumeSig(); processNextTask(); } void TaskProcessor::processNextTask() { QMutexLocker locker(&m_mutex); if (m_taskQueue.isEmpty()) { qDebug() << "All tasks finished."; emit allTasksFinished(); return; } // 取出队列中的下一个任务 std::function<void()> task = m_taskQueue.dequeue(); // 在运行状态下开始任务,发出任务开始信号 emit taskStarted(); qDebug() << "Processing a task..."; // 这里可以在一个独立线程中运行任务,避免阻塞状态机 // 例如:QThread::sleep() 或者使用 QtConcurrent task(); // 任务执行完成,发出任务结束信号 emit taskFinished(); }Qt之QStateMachine等待由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Qt之QStateMachine等待”