一个状态机管理了一个状态的集合以及这些状态之间的过渡,这就形成了一个状态图,一但这个状态图形成了,就可以执行这个状态图。
状态机提供了一种图形的方法来建模一个系统对于外部刺激怎么样反应。
#include <QApplication>
#include <QState>
#include <QStateMachine>
#include <QPushButton>
#include <QVariant>
#include <QFinalState>
#include <QLayout>
//Qt的状态机是层次的,是事件驱动的,使用到了事件循环,那么就是异步的
int main(int argc, char* argv[])
{
QApplication app(argc,argv);
QStateMachine sMachine;//一个状态机对象
QState s;//和fState在同一个层次
QState s1;//3个状态对象
s1.setParent(&s);
QState s2;
s2.setParent(&s);
QState s3;
s3.setParent(&s);
s.setInitialState(&s1);//一组状态中要指定一组状态中的初始状态
QFinalState fState;
QWidget w;
QHBoxLayout layout;
QPushButton button;
QPushButton qButton;
layout.addWidget(&button);
layout.addWidget(&qButton);
w.setLayout(&layout);
//给每个状态添加过渡
s.addTransition(&qButton,SIGNAL(clicked()),&fState);//s -- > finalState,但是在这组内的状态对于这个过渡可以覆盖
//s2.addTransition(&qButton,SIGNAL(clicked()),&s3);//如果添加这一个句,那么在s2点击qButton按钮
//就不会退出,只是转向了s3
s1.addTransition(&button,SIGNAL(clicked()),&s2);//s1为这个过渡的始状态,s2为末状态
s2.addTransition(&button,SIGNAL(clicked()),&s3);
s3.addTransition(&button,SIGNAL(clicked()),&s1);
//每个状态进入时,设置指定对象指定项指定的值
s1.assignProperty(&button,"text","s1-->s2");
s2.assignProperty(&button,"text","s2-->s3");
s3.assignProperty(&button,"text","s3-->s1");
//也可能重写 QAbstractState::onEntry()和QAbstractState::onExit()函数
//在UML的状态图中,每个状态在进入状态和离开状态的时候都会进行相关的操作
//这个可以通过这两个信号来解决,也可通过继承来重写上述的两个函数
QObject::connect(&s3,SIGNAL(entered()),&button,SLOT(showMinimized()));
QObject::connect(&s3,SIGNAL(exited()),&button,SLOT(showMaximized()));
sMachine.addState(&s);//对于状态机只是添加顶层的状态
// sMachine.addState(&s1);
// sMachine.addState(&s2);
// sMachine.addState(&s3);
sMachine.addState(&fState);
QObject::connect(&sMachine,SIGNAL(finished()),&app,SLOT(quit()));
//设置状态机的初始状态
//sMachine.setInitialState(&s1);
sMachine.setInitialState(&s);//对于状态机的初始化,只是使用顶层的状态初始化,所以每个顶层如果是
//一组状态,那么就要指定这组状态的初始化状态
w.show();
//状态机开启
sMachine.start();
//可以通过给状态分组来实现状态过渡的共享,比如我们希望在任何状态下我们都能够退出,
//那么这个退出状态就是比其他的状态具有高的状态层次,那么我们就要将其他的状态封装在
//合适的与退出状态同层次的一个高阶的状态层次中
return app.exec();
}