流程设计状态图
#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. 每个子状态设置初始状态,也就是子状态第一个状态