Qt 状态机编程,双层状态机,实现暂停恢复

news/2024/9/24 16:54:12/

路流程
流程设计状态图

#ifndef WORKMACHINE_H
#define WORKMACHINE_H#include <QObject>
#include <QStateMachine>
#include <QHistoryState>
#include <QFinalState>#include "WorkThread.h"class WorkMachine : public QObject
{Q_OBJECT
public:explicit WorkMachine(QObject *parent = nullptr);~WorkMachine();void startMachine();void runMachineWorkFlow();void pauseMachine();void resumeMachine();signals:void sigMachineLog(QString log);void sigNextState();void sigPauseMachine();void sigResumeMachine();void sigMachineState(int state);private:void initMachine();void initStateTrans();void initWork();private:// 待机-》 (开门-》关门-》清洗-》甩干-》)  结束QStateMachine   m_machine;QState          *m_idleState;QState          *m_stateOpen;QState          *m_stateClose;QState          *m_groupStateWork;QState          *m_stateWash;QState          *m_stateDry;QState          *m_statePause;QHistoryState   *m_stateHistoryWork;bool            m_isPause;WorkThread      *m_workThread;
};#endif // WORKMACHINE_H
#include "WorkMachine.h"
#include <QDebug>WorkMachine::WorkMachine(QObject *parent): QObject{parent}
{initMachine();initStateTrans();initWork();m_isPause = false;
}WorkMachine::~WorkMachine()
{m_groupStateWork->deleteLater();
}void WorkMachine::startMachine()
{if (m_machine.isRunning()) {qDebug() << " ********* stop **********";m_machine.stop();emit sigMachineState(0);}else {qDebug() << "******** machine start work ********";m_machine.start();emit sigMachineState(1);//emit sigMachineLog("******** machine start work ********")}
}void WorkMachine::runMachineWorkFlow()
{emit sigNextState();
}void WorkMachine::pauseMachine()
{emit sigPauseMachine();m_isPause = true;
}void WorkMachine::resumeMachine()
{emit sigResumeMachine();m_isPause = false;
}void WorkMachine::initMachine()
{m_workThread = new WorkThread();m_idleState = new QState(&m_machine);m_idleState->setObjectName("initialState");m_statePause = new QState(&m_machine);m_statePause->setObjectName("pauseState");m_groupStateWork = new QState(&m_machine);m_groupStateWork->setObjectName("stateWork");m_stateOpen = new QState(m_groupStateWork);m_stateOpen->setObjectName("openState");QState *open1 = new QState(m_stateOpen);open1->setObjectName("open1State");QState *open2 = new QState(m_stateOpen);QFinalState *openFinal  = new QFinalState(m_stateOpen);open2->setObjectName("open2State");m_stateOpen->setInitialState(open1);open1->addTransition(this, &WorkMachine::sigNextState, open2);open2->addTransition(this, &WorkMachine::sigNextState, openFinal);connect(open1, &QState::entered, this, [this](){m_workThread->startTask("step 1 open1", 500);});connect(open2, &QState::entered, this, [this](){m_workThread->startTask("step 1 open2", 500);});m_stateClose = new QState(m_groupStateWork);m_stateClose->setObjectName("closeState");m_stateWash = new QState(m_groupStateWork);m_stateWash->setObjectName("stateWash");m_stateDry = new QState(m_groupStateWork);m_stateDry->setObjectName("stateDry");m_stateHistoryWork = new QHistoryState(m_groupStateWork);m_stateHistoryWork->setObjectName("historyState");m_stateHistoryWork->setDefaultState(m_stateWash);m_stateHistoryWork->setHistoryType(QHistoryState::DeepHistory);m_groupStateWork->setChildMode(QState::ExclusiveStates);m_groupStateWork->setInitialState(m_stateHistoryWork);m_machine.setInitialState(m_idleState);
}void WorkMachine::initStateTrans()
{m_groupStateWork->addTransition(this, &WorkMachine::sigPauseMachine, m_statePause);m_statePause->addTransition(this, &WorkMachine::sigResumeMachine, m_stateHistoryWork);connect(m_workThread, &WorkThread::finished, this, [this](){if (m_isPause) {}else {emit sigNextState();}});m_idleState->addTransition(this, &WorkMachine::sigNextState, m_stateOpen);//m_stateOpen->addTransition(this, &WorkMachine::sigNextState, m_stateClose);m_stateOpen->addTransition(m_stateOpen, &QState::finished, m_stateClose);m_stateClose->addTransition(this, &WorkMachine::sigNextState, m_stateWash);m_stateWash->addTransition(this, &WorkMachine::sigNextState, m_stateDry);m_stateDry->addTransition(this, &WorkMachine::sigNextState, m_idleState);
}void WorkMachine::initWork()
{connect(m_idleState, &QState::entered, this, [this](){qDebug() << "init state";});connect(m_stateHistoryWork, &QState::entered, this, [this](){qDebug() << "m_stateHistoryWork state enter";});connect(m_stateOpen, &QState::entered, this, [this](){m_workThread->startTask("step 1 Open");});connect(m_stateClose, &QState::entered, this, [this](){m_workThread->startTask("step 2 Close");});connect(m_groupStateWork, &QState::entered, this, [this](){qDebug() << "Work state enter";});connect(m_stateWash, &QState::entered, this, [this](){m_workThread->startTask("step 3 Wash", 2000);});connect(m_stateDry, &QState::entered, this, [this](){m_workThread->startTask("step 4 Dry", 2000);});connect(m_statePause, &QState::entered, this, [this](){qDebug() << "pause";});
}
#ifndef WORKTHREAD_H
#define WORKTHREAD_H#include <QObject>
#include <QThread>class WorkThread: public QThread
{
public:WorkThread();void startTask(QString log, int timems=500);void run() override;private:QString   m_log;int       m_time;
};#endif // WORKTHREAD_H
#include "WorkThread.h"
#include <QDebug>WorkThread::WorkThread() {}void WorkThread::startTask(QString log, int timems)
{m_log = log;m_time = timems;this->start();
}void WorkThread::run()
{QThread::msleep(100);qDebug() << m_log  + " start running ...";QThread::msleep(m_time);qDebug() << m_log  + " end";
}

UI 控制类

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "WorkMachine.h"QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnRun_clicked();private:Ui::Widget *ui;WorkMachine  m_machine;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->btnStart, &QPushButton::clicked, this, [this](){m_machine.startMachine();});connect(ui->btnPause, &QPushButton::clicked, this, [this](){m_machine.pauseMachine();});connect(ui->btnResume, &QPushButton::clicked, this, [this](){m_machine.resumeMachine();});connect(&m_machine, &WorkMachine::sigMachineState, this, [this](bool isRun){ui->btnPause->setEnabled(isRun);});
}Widget::~Widget()
{delete ui;
}void Widget::on_btnRun_clicked()
{m_machine.runMachineWorkFlow();
}

设计思路:
1 .每个状态对应一个流程
2. 每个状态进入后开始执行流程动作
3. 状态进入流程开始执行,执行结束线程结束
4. 线程结束信号控制转移到下一个状态,也就是下一个流程继续往下走
5. 暂停时候主动触发 pause 信号状态机从 work 状态跳出到 pause 状态
6. 恢复时候从 pause 状态回到 history 状态,根据需要设置历史状态深浅,是否记录子状态,还是只记录第一层状态
7. 每个子状态流程末尾使用 final 状态标记,使用他的finished 信号进行状态转移
8. 每个子状态设置初始状态,也就是子状态第一个状态


http://www.ppmy.cn/news/1529896.html

相关文章

汽车总线之---- CAN FD总线

CAN FD 最高可支持8M/s的通信速率&#xff0c;从传统CAN到CAN FD的转换是很容易实施和推广的。 CAN FD报文的帧&#xff1a;标准帧&#xff0c;扩展帧 CAN FD 标准帧结构 CAN FD 报文的标准帧与CAN 报文的标准帧的区别 CAN FD 报文的标准帧与CAN FD报文的扩展帧的区别&…

C++primer第十一章使用类(矢量随机游走实例)

操作符重载 操作符重载(operator overoading)是一种形式的 C多态。 第8章介绍了C是如何使用户能够定义多个名称相同但特征标(参数列表)不同的函数的。这被称为函数重载(function overloading)或函数多态(functional polymorphism)&#xff0c;旨在让您能够用同名的函数来完成…

简历信息提取系统源码分享

简历信息提取检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

HP 电脑 - 管理电源选项 (Windows 10)

HP 电脑 - 管理电源选项 (Windows 10) 您可以选择 Windows 电源计划减少电脑使用的电量&#xff0c;最大限度提高性能&#xff0c;或者实现二者的完美平衡。此外&#xff0c;本文档还提供了多种关闭电脑的方法以及如何使用电源模式和解决电源问题等信息。 使用 Windows 电源计…

Java | Leetcode Java题解之第421题数组中的两个数的最大异或值

题目&#xff1a; 题解&#xff1a; class Solution {// 字典树的根节点Trie root new Trie();// 最高位的二进制位编号为 30static final int HIGH_BIT 30;public int findMaximumXOR(int[] nums) {int n nums.length;int x 0;for (int i 1; i < n; i) {// 将 nums[i…

【C++】—— stack queue deque

【C】—— stack & queue & deque 1 stack 与 queue 的函数接口2 适配器2.1 发现问题2.2 什么是适配器 3 stack 与 queue的模拟实现3.1 栈的基础框架3.2 栈的模拟实现3.3 队列的模拟实现 4 模板的按需实例化5 deque 的简单介绍5.1 vector 与list对比5.1.1 vector5.1.2 …

JWT双令牌认证实现无感Token自动续约

一、JWT概念 JSON Web Token (JWT)是一个开放标准(RFC 7519) &#xff0c;它定义了一种紧凑和自包含的方式&#xff0c;用于作为 JSON 对象在各方之间安全地传输信息。此信息可以进行验证和信任&#xff0c;因为它是经过数字签名的。JWT 可以使用机密(使用 HMAC 算法)或使用 R…

springboot中药材进存销管理系统

基于springbootvue实现的中药材进存销管理系统 &#xff08;源码L文ppt&#xff09;4-079 4 系统总体设计 4.1系统功能结构设计图 根据需求说明设计系统各功能模块。采用模块化设计方法实现一个复杂结构进行简化&#xff0c;分成一个个小的容易解决的板块&#xff0c;然…