当前位置: 首页 > article >正文

Qt之QStateMachine等待

在项目中经常需要等待,我们模拟0-30的数,假如我们其中5, 25的数需要进行等待,等待用户处理完自己事情后,按下按钮继续,找Qt的项目中有一个

QStateMachine

qstatemmachine类提供了一个分层有限状态机。
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();


}


http://www.kler.cn/a/569166.html

相关文章:

  • 【每日八股】MySQL篇(四):索引(下)
  • 计算机毕业设计SpringBoot+Vue.js人力资源管理系统(源码+文档+PPT+讲解)
  • 【音视频】VLC播放器
  • Hive-08之数据仓库之建模、分析
  • 【Python 语法】Python 数据结构
  • Deepseek助力思维导图与流程图制作:高效出图新选择
  • LeetCode 热题100 3. 无重复字符的最长子串
  • CF 118A.String Task(Java实现)
  • Git与GitHub实战指南:从入门到高效协作
  • 华宇TAS应用中间件与统信最新版本操作系统完成兼容互认证
  • React Axios + Django 跨域解决方案详解
  • 实现 Leaflet 多类型点位标记与聚合功能的实战经验分享
  • 2025最新Nginx高频面试题
  • 数据库操作命令详解:CREATE、ALTER、DROP 的使用与实践
  • C# 装箱(Boxing)与拆箱(Unboxing)
  • fastadmin 后台商品sku(vue)
  • 前后端传值响应下载文件压缩包
  • Docker入门指南:Windows下docker配置镜像源加速下载
  • 【计算机网络】TCP协议相关总结,TCP可靠性的生动讲解
  • Android Studio中gradle一栏中出现nothing to show 提示的解决方法