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

流程设计状态图

cpp 复制代码
#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
cpp 复制代码
#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";
    });
}
cpp 复制代码
#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
cpp 复制代码
#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 控制类

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "WorkMachine.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btnRun_clicked();

private:
    Ui::Widget *ui;
    WorkMachine  m_machine;
};
#endif // WIDGET_H
cpp 复制代码
#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 .每个状态对应一个流程

  1. 每个状态进入后开始执行流程动作

  2. 状态进入流程开始执行,执行结束线程结束

  3. 线程结束信号控制转移到下一个状态,也就是下一个流程继续往下走

  4. 暂停时候主动触发 pause 信号状态机从 work 状态跳出到 pause 状态

  5. 恢复时候从 pause 状态回到 history 状态,根据需要设置历史状态深浅,是否记录子状态,还是只记录第一层状态

  6. 每个子状态流程末尾使用 final 状态标记,使用他的finished 信号进行状态转移

  7. 每个子状态设置初始状态,也就是子状态第一个状态

相关推荐
Predestination王瀞潞1 小时前
IO操作(Num22)
开发语言·c++
宋恩淇要努力3 小时前
C++继承
开发语言·c++
沿着路走到底4 小时前
python 基础
开发语言·python
沐知全栈开发5 小时前
C# 委托(Delegate)
开发语言
feiyangqingyun5 小时前
有难度哦/Qt基于通用地图组件实现航迹规划和模拟/动态标注轨迹线/带序号和方向箭头指示
qt·航迹规划和模拟
江公望5 小时前
Qt qmlRegisterSingletonType()函数浅谈
c++·qt
HyEISN5 小时前
关于 Qt 6.10.0 中 FolderListModel 返回 undefined 路径
qt
任子菲阳5 小时前
学Java第三十四天-----抽象类和抽象方法
java·开发语言
csbysj20206 小时前
如何使用 XML Schema
开发语言
R6bandito_6 小时前
STM32中printf的重定向详解
开发语言·经验分享·stm32·单片机·嵌入式硬件·mcu