咱们在使用状态机时,可能在执行一组状态的过程当中跳转到一个新状态执行完任务后还须要跳转到原来执行被打断的地方,Qt的状态机框架为咱们提供了QHistoryState类。这个类只要将它加入到这组状态中,它就会记住固然执行到的这组状态中的哪个。app
#include <QApplication> #include <QState> #include <QStateMachine> #include <QPushButton> #include <QVariant> #include <QFinalState> #include <QLayout> #include <QHistoryState> #include <QLabel> #include <QMessageBox> #include <QtDebug> #include <QAbstractTransition> //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);//一组状态中要指定一组状态中的初始状态 QHistoryState sh;//记录s组状态被打断的状态 sh.setParent(&s); QFinalState fState; QState is;//中断状态 QWidget w; QHBoxLayout layout; QPushButton button; QPushButton qButton; qButton.setText(QObject::tr("退出")); QPushButton iButton; iButton.setText(QObject::tr("打断")); QLabel showLabel(QObject::tr("sssssss")); layout.addWidget(&button); layout.addWidget(&qButton); layout.addWidget(&iButton); layout.addWidget(&showLabel); w.setLayout(&layout); QMessageBox box(&w); box.addButton(QMessageBox::Ok); box.setText(QObject::tr("打断了,如今是is")); box.setIcon(QMessageBox::Information); 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.assignProperty(&button,"text","s2"); s3.assignProperty(&button,"text","s3"); //给每一个状态添加过渡 s.addTransition(&qButton,SIGNAL(clicked()),&fState);//s -- > finalState,可是在这组内的状态对于这个过渡能够覆盖 //s2.addTransition(&qButton,SIGNAL(clicked()),&s3);//若是添加这一个句,那么在s2点击qButton按钮 //就不会退出,只是转向了s3 s.addTransition(&iButton,SIGNAL(clicked()),&is); is.addTransition(&sh); QObject::connect(&is,SIGNAL(entered()),&box,SLOT(exec())); //也可能重写 QAbstractState::onEntry()和QAbstractState::onExit()函数 //在UML的状态图中,每一个状态在进入状态和离开状态的时候都会进行相关的操做 //这个能够经过这两个信号来解决,也可经过继承来重写上述的两个函数 QObject::connect(&s3,SIGNAL(entered()),&w,SLOT(showMinimized())); QObject::connect(&s3,SIGNAL(exited()),&w,SLOT(showMaximized())); QObject::connect(&sMachine,SIGNAL(finished()),&app,SLOT(quit())); sMachine.addState(&s);//对于状态机只是添加顶层的状态 // sMachine.addState(&s1); // sMachine.addState(&s2); // sMachine.addState(&s3); sMachine.addState(&fState); sMachine.addState(&is); //设置状态机的初始状态 //sMachine.setInitialState(&s1); sMachine.setInitialState(&s);//对于状态机的初始化,只是使用顶层的状态初始化,因此每一个顶层若是是 //一组状态,那么就要指定这组状态的初始化状态 w.show(); //状态机开启 sMachine.start(); //能够经过给状态分组来实现状态过渡的共享,好比咱们但愿在任何状态下咱们都可以退出, //那么这个退出状态就是比其余的状态具备高的状态层次,那么咱们就要将其余的状态封装在 //合适的与退出状态同层次的一个高阶的状态层次中 return app.exec(); }上面的这个例子,在s状态组中添加了一个 QHistoryState对象记录当前的执行到的状态。在咱们点击中断按钮后,咱们从一个s的子状态跳转到is状态,而后在跳转到s被打断的状态。
以下图所示:框架
此时咱们点击s2会跳转到s3,进入s3会触发异步
QObject::connect(&s3,SIGNAL(entered()),&w,SLOT(showMinimized()));这个信号和槽,窗体会最小化
如今在点击打断按钮,从s3跳转到is状态会触发函数
QObject::connect(&s3,SIGNAL(exited()),&w,SLOT(showMaximized()));因此会最大化,而后弹出一个阻塞的QMessagebox,当咱们点击ok,is会转到记录的那个转出状态也就是s3,又触发了
QObject::connect(&s3,SIGNAL(entered()),&w,SLOT(showMinimized()));因此会最小化。