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

打印 上一主题 下一主题

主题 1685|帖子 1685|积分 5055


流程设计状态图
  1. #ifndef WORKMACHINE_H
  2. #define WORKMACHINE_H
  3. #include <QObject>
  4. #include <QStateMachine>
  5. #include <QHistoryState>
  6. #include <QFinalState>
  7. #include "WorkThread.h"
  8. class WorkMachine : public QObject
  9. {
  10.     Q_OBJECT
  11. public:
  12.     explicit WorkMachine(QObject *parent = nullptr);
  13.     ~WorkMachine();
  14.     void startMachine();
  15.     void runMachineWorkFlow();
  16.     void pauseMachine();
  17.     void resumeMachine();
  18. signals:
  19.     void sigMachineLog(QString log);
  20.     void sigNextState();
  21.     void sigPauseMachine();
  22.     void sigResumeMachine();
  23.     void sigMachineState(int state);
  24. private:
  25.     void initMachine();
  26.     void initStateTrans();
  27.     void initWork();
  28. private:
  29.     // 待机-》 (开门-》关门-》清洗-》甩干-》)  结束
  30.     QStateMachine   m_machine;
  31.     QState          *m_idleState;
  32.     QState          *m_stateOpen;
  33.     QState          *m_stateClose;
  34.     QState          *m_groupStateWork;
  35.     QState          *m_stateWash;
  36.     QState          *m_stateDry;
  37.     QState          *m_statePause;
  38.     QHistoryState   *m_stateHistoryWork;
  39.     bool            m_isPause;
  40.     WorkThread      *m_workThread;
  41. };
  42. #endif // WORKMACHINE_H
复制代码
  1. #include "WorkMachine.h"
  2. #include <QDebug>
  3. WorkMachine::WorkMachine(QObject *parent)
  4.     : QObject{parent}
  5. {
  6.     initMachine();
  7.     initStateTrans();
  8.     initWork();
  9.     m_isPause = false;
  10. }
  11. WorkMachine::~WorkMachine()
  12. {
  13.     m_groupStateWork->deleteLater();
  14. }
  15. void WorkMachine::startMachine()
  16. {
  17.     if (m_machine.isRunning()) {
  18.         qDebug() << " ********* stop **********";
  19.         m_machine.stop();
  20.         emit sigMachineState(0);
  21.     }
  22.     else {
  23.         qDebug() << "******** machine start work ********";
  24.         m_machine.start();
  25.         emit sigMachineState(1);
  26.         //emit sigMachineLog("******** machine start work ********")
  27.     }
  28. }
  29. void WorkMachine::runMachineWorkFlow()
  30. {
  31.     emit sigNextState();
  32. }
  33. void WorkMachine::pauseMachine()
  34. {
  35.     emit sigPauseMachine();
  36.     m_isPause = true;
  37. }
  38. void WorkMachine::resumeMachine()
  39. {
  40.     emit sigResumeMachine();
  41.     m_isPause = false;
  42. }
  43. void WorkMachine::initMachine()
  44. {
  45.     m_workThread = new WorkThread();
  46.     m_idleState = new QState(&m_machine);
  47.     m_idleState->setObjectName("initialState");
  48.     m_statePause = new QState(&m_machine);
  49.     m_statePause->setObjectName("pauseState");
  50.     m_groupStateWork = new QState(&m_machine);
  51.     m_groupStateWork->setObjectName("stateWork");
  52.     m_stateOpen = new QState(m_groupStateWork);
  53.     m_stateOpen->setObjectName("openState");
  54.     QState *open1 = new QState(m_stateOpen);
  55.     open1->setObjectName("open1State");
  56.     QState *open2 = new QState(m_stateOpen);
  57.     QFinalState *openFinal  = new QFinalState(m_stateOpen);
  58.     open2->setObjectName("open2State");
  59.     m_stateOpen->setInitialState(open1);
  60.     open1->addTransition(this, &WorkMachine::sigNextState, open2);
  61.     open2->addTransition(this, &WorkMachine::sigNextState, openFinal);
  62.     connect(open1, &QState::entered, this, [this](){
  63.         m_workThread->startTask("step 1 open1", 500);
  64.     });
  65.     connect(open2, &QState::entered, this, [this](){
  66.         m_workThread->startTask("step 1 open2", 500);
  67.     });
  68.     m_stateClose = new QState(m_groupStateWork);
  69.     m_stateClose->setObjectName("closeState");
  70.     m_stateWash = new QState(m_groupStateWork);
  71.     m_stateWash->setObjectName("stateWash");
  72.     m_stateDry = new QState(m_groupStateWork);
  73.     m_stateDry->setObjectName("stateDry");
  74.     m_stateHistoryWork = new QHistoryState(m_groupStateWork);
  75.     m_stateHistoryWork->setObjectName("historyState");
  76.     m_stateHistoryWork->setDefaultState(m_stateWash);
  77.     m_stateHistoryWork->setHistoryType(QHistoryState::DeepHistory);
  78.     m_groupStateWork->setChildMode(QState::ExclusiveStates);
  79.     m_groupStateWork->setInitialState(m_stateHistoryWork);
  80.     m_machine.setInitialState(m_idleState);
  81. }
  82. void WorkMachine::initStateTrans()
  83. {
  84.     m_groupStateWork->addTransition(this, &WorkMachine::sigPauseMachine, m_statePause);
  85.     m_statePause->addTransition(this, &WorkMachine::sigResumeMachine, m_stateHistoryWork);
  86.     connect(m_workThread, &WorkThread::finished, this, [this](){
  87.         if (m_isPause) {
  88.         }
  89.         else {
  90.             emit sigNextState();
  91.         }
  92.     });
  93.     m_idleState->addTransition(this, &WorkMachine::sigNextState, m_stateOpen);
  94.     //m_stateOpen->addTransition(this, &WorkMachine::sigNextState, m_stateClose);
  95.     m_stateOpen->addTransition(m_stateOpen, &QState::finished, m_stateClose);
  96.     m_stateClose->addTransition(this, &WorkMachine::sigNextState, m_stateWash);
  97.     m_stateWash->addTransition(this, &WorkMachine::sigNextState, m_stateDry);
  98.     m_stateDry->addTransition(this, &WorkMachine::sigNextState, m_idleState);
  99. }
  100. void WorkMachine::initWork()
  101. {
  102.     connect(m_idleState, &QState::entered, this, [this](){
  103.         qDebug() << "init state";
  104.     });
  105.     connect(m_stateHistoryWork, &QState::entered, this, [this](){
  106.         qDebug() << "m_stateHistoryWork state enter";
  107.     });
  108.     connect(m_stateOpen, &QState::entered, this, [this](){
  109.         m_workThread->startTask("step 1 Open");
  110.     });
  111.     connect(m_stateClose, &QState::entered, this, [this](){
  112.         m_workThread->startTask("step 2 Close");
  113.     });
  114.     connect(m_groupStateWork, &QState::entered, this, [this](){
  115.         qDebug() << "Work state enter";
  116.     });
  117.     connect(m_stateWash, &QState::entered, this, [this](){
  118.         m_workThread->startTask("step 3 Wash", 2000);
  119.     });
  120.     connect(m_stateDry, &QState::entered, this, [this](){
  121.         m_workThread->startTask("step 4 Dry", 2000);
  122.     });
  123.     connect(m_statePause, &QState::entered, this, [this](){
  124.         qDebug() << "pause";
  125.     });
  126. }
复制代码
  1. #ifndef WORKTHREAD_H
  2. #define WORKTHREAD_H
  3. #include <QObject>
  4. #include <QThread>
  5. class WorkThread: public QThread
  6. {
  7. public:
  8.     WorkThread();
  9.     void startTask(QString log, int timems=500);
  10.     void run() override;
  11. private:
  12.     QString   m_log;
  13.     int       m_time;
  14. };
  15. #endif // WORKTHREAD_H
复制代码
  1. #include "WorkThread.h"
  2. #include <QDebug>
  3. WorkThread::WorkThread() {
  4. }
  5. void WorkThread::startTask(QString log, int timems)
  6. {
  7.     m_log = log;
  8.     m_time = timems;
  9.     this->start();
  10. }
  11. void WorkThread::run()
  12. {
  13.     QThread::msleep(100);
  14.     qDebug() << m_log  + " start running ...";
  15.     QThread::msleep(m_time);
  16.     qDebug() << m_log  + " end";
  17. }
复制代码
UI 控制类
  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include "WorkMachine.h"
  5. QT_BEGIN_NAMESPACE
  6. namespace Ui {
  7. class Widget;
  8. }
  9. QT_END_NAMESPACE
  10. class Widget : public QWidget
  11. {
  12.     Q_OBJECT
  13. public:
  14.     Widget(QWidget *parent = nullptr);
  15.     ~Widget();
  16. private slots:
  17.     void on_btnRun_clicked();
  18. private:
  19.     Ui::Widget *ui;
  20.     WorkMachine  m_machine;
  21. };
  22. #endif // WIDGET_H
复制代码
  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. Widget::Widget(QWidget *parent)
  4.     : QWidget(parent)
  5.     , ui(new Ui::Widget)
  6. {
  7.     ui->setupUi(this);
  8.     connect(ui->btnStart, &QPushButton::clicked, this, [this](){
  9.         m_machine.startMachine();
  10.     });
  11.     connect(ui->btnPause, &QPushButton::clicked, this, [this](){
  12.         m_machine.pauseMachine();
  13.     });
  14.     connect(ui->btnResume, &QPushButton::clicked, this, [this](){
  15.         m_machine.resumeMachine();
  16.     });
  17.     connect(&m_machine, &WorkMachine::sigMachineState, this, [this](bool isRun){
  18.         ui->btnPause->setEnabled(isRun);
  19.     });
  20. }
  21. Widget::~Widget()
  22. {
  23.     delete ui;
  24. }
  25. void Widget::on_btnRun_clicked()
  26. {
  27.     m_machine.runMachineWorkFlow();
  28. }
复制代码
设计思绪:
1 .每个状态对应一个流程
2. 每个状态进入后开始执行流程动作
3. 状态进入流程开始执行,执行结束线程结束
4. 线程结束信号控制转移到下一个状态,也就是下一个流程继续往下走
5. 停息时候主动触发 pause 信号状态机从 work 状态跳出到 pause 状态
6. 恢复时候从 pause 状态回到 history 状态,根据必要设置汗青状态深浅,是否记载子状态,还是只记载第一层状态
7. 每个子状态流程末尾使用 final 状态标记,使用他的finished 信号进行状态转移
8. 每个子状态设置初始状态,也就是子状态第一个状态

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表