前言

上一篇博客中已经介绍了Qt状态机的基础概念和用法,文章在这里,接下来继续介绍Qt状态机的使用。

历史状态的保存和恢复

前一个示例中,我们通过一个按钮中断状态机,在此基础上,如果我们中断状态机过后想再次回到之前停下来的地方,这时候就需要使用到历史状态
历史状态是一个假想的状态,它表示了父状态上次退出时的子状态。

历史状态通常创建为想要保存的那个状态的子状态。这样在程序运行时,当状态机检测到这种状态的存在就会在父状态退出时自动记录当前的子状态。连接到历史状态的过渡实际上就是连接到状态机上次保存的子状态,状态机会自动的将过渡前移到正在的子状态。下面是执行流程:

先看一下效果图:

代码如下:

#include <QWidget>
#include <QState>
#include <QStateMachine>
#include <QFinalState>
#include <QHistoryState>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();private slots:void onOutputMessage();private:Ui::Widget *ui;QStateMachine * m_pStateMachine = nullptr;QState * m_pState1 = nullptr;QState * m_pState2 = nullptr;QState * m_pState3 = nullptr;QState * m_pStateParent = nullptr;QFinalState * m_pFinalState = nullptr;QHistoryState * m_pHistoryState = nullptr;
};
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);m_pStateMachine = new QStateMachine(this);m_pStateParent = new QState();m_pState1 = new QState(m_pStateParent);m_pState2 = new QState(m_pStateParent);m_pState3 = new QState(m_pStateParent);m_pStateParent->assignProperty(ui->label, "text", "In s1");m_pState1->assignProperty(ui->btn2,"pos",QPoint(20,40));m_pState2->assignProperty(ui->btn2,"pos",QPoint(80,40));m_pState3->assignProperty(ui->btn2,"pos",QPoint(120,40));m_pState1->addTransition(ui->btn1,SIGNAL(clicked()),m_pState2);m_pState2->addTransition(ui->btn1,SIGNAL(clicked()),m_pState3);m_pState3->addTransition(ui->btn1,SIGNAL(clicked()),m_pState1);m_pStateParent->setInitialState(m_pState1);m_pFinalState = new QFinalState();m_pStateParent->addTransition(ui->btn3,SIGNAL(clicked()),m_pFinalState);m_pStateMachine->addState(m_pStateParent);m_pStateMachine->addState(m_pFinalState);m_pStateMachine->setInitialState(m_pStateParent);m_pHistoryState = new QHistoryState(m_pStateParent);QState *s3 = new QState();s3->assignProperty(ui->label, "text", "In s3");QMessageBox *mbox = new QMessageBox(this);mbox->addButton(QMessageBox::Ok);mbox->setText("Interrupted!");mbox->setIcon(QMessageBox::Information);QObject::connect(s3, SIGNAL(entered()), mbox, SLOT(exec()));s3->addTransition(m_pHistoryState);m_pStateMachine->addState(s3);m_pStateParent->addTransition(ui->btn2, SIGNAL(clicked()), s3);m_pStateMachine->start();}Widget::~Widget()
{delete ui;
}

使用并行状态来避免过多的状态组合

当需要同步执行多个状态时,可以将状态机设置成并行状态组,进入到并行状态后,所有子状态都会同时开始运行,每个子状态的过渡都会正常执行。但是,每一个子状态都有可能退出父状态,如果这样,父状态和它所有的子状态都会结束。

在Qt状态机框架的并行机制里有一个交错语义。所有的并行操作都是在一个事件处理中独立的、原子的被执行,所以没有事件能打断并行操作。但是,事件仍然是被顺序的处理的,因为状态机本身是单线程的。举个栗子,如果有两个过渡退出同一个并行状态组,并且它们的触发条件同时被满足。在这种情况下,第二个被处理的退出事件将没有任何实际的反应,因为第一个事件已经导致了状态机从并行状态中结束。

并行状态示例:

      QState *s1 = new QState(QState::ParallelStates);// s11 and s12 will be entered in parallelQState *s11 = new QState(s1);QState *s12 = new QState(s1);

检测组合状态的结束

子状态可以是一个final状态;当进入一个final子状态时,父状态会发出finished() 信号。下图显示了一个组合状态s1在做了一系列的处理后进入了一个final状态:

当s1进入一个final子状态时,s1会自动发出finished() 信号。我们使用一个 信号过渡 来触发一个状态转换:

s1->addTransition(s1, SIGNAL(finished()), s2);

在组合状态中使用final状态对应想隐藏组合状态的内部细节来说是非常有用的。也就是说,对应外部世界来说,只需要进入这个状态,然后等待这个状态的完成信号即可。这对于构建复杂的状态机来说是一种强有力的的封装和抽象机制。但是,对应并行状态组来说,finishe()信号只有在所以的子状态都进入final状态时才会发出。

无目标状态的过渡

一个Transition并不是一定要有一个目标状态,并且没有目标状态的过渡也可以像其他过渡一样被触发。区别是当一个没有目标状态的过渡被触发时,不会导致任何状态的改变。这运行你在状态机进入某个状态时响应一个信号或事件而不必离开那个状态。

示例:

    m_pStateMachine = new QStateMachine(this);m_pState1 = new QState();QSignalTransition *trans = new QSignalTransition(ui->btn1, SIGNAL(clicked()));m_pState1->addTransition(trans);m_pStateMachine->addState(m_pState1);m_pStateMachine->setInitialState(m_pState1);QMessageBox *mbox = new QMessageBox(this);mbox->addButton(QMessageBox::Ok);mbox->setText("Interrupted!");mbox->setIcon(QMessageBox::Information);QObject::connect(trans, SIGNAL(triggered()), mbox, SLOT(exec()));m_pStateMachine->start();

当每次点击按钮时,都会弹出消息框,但是状态会一直停留在m_pState1,如果显示的把状态机的状态设置为s1,s1状态会结束,然后重新进入该状态。

Qt状态机框架介绍(二)相关推荐

  1. Qt状态机框架介绍(一)

    概述 状态机,简写为FSM(Finite State Machine),状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作.完成特定操作的控制中心 ...

  2. 从Qt 4到Qt 5(二)Qt 5框架介绍

    导语 上一节已经安装好Qt 5.2,并将一个Qt 4程序迁移到了Qt 5上.其中我们讲到Qt 5中QApplication类已经不在QtGui模块中了,而且所有的Qt 5图形界面程序都必须在.pro项 ...

  3. Qt状态机框架(01):The State Machine Framework【官翻】

    文章目录 一.前言 二.状态机框架中的类 三.简单的状态机示例 3.1 首先,我们创建状态机和状态: 3.2 然后,我们使用QState::addTransition()函数来创建转换: 3.3 然后 ...

  4. [Q学习]14 Qt状态机框架——进入和退出状态2

    2 关联信号槽 Qt状态机有这样一个特性:进入某个状态时会触发QState::entered()信号,离开状态时触发QState::exited()信号,如此,我们使用槽函数关联这两个信号就可以做一些 ...

  5. 使用Qt动画框架设计角色的二维动画

    使用Qt动画框架设计角色的二维动画 Qt的动画框架是Qt4.6新添加的一个重要的特性,有了它,开发人员可以制作激动人心的动画界面,而不必局限于单调的固定窗口了,可以说,Qt动画框架是其它界面库少见的功 ...

  6. 如何保证Qt状态机的最佳性能

    如何保证Qt状态机的最佳性能 How to ensure the best Qt state machine performance 如果您使用Qt进行应用程序开发,并且使用状态机,那么很可能您正在使 ...

  7. nodeJs--egg框架介绍

    egg框架 一.egg框架介绍 二.约定规则 三.主要模块 路由(router.js) 控制器(Controller.js) 服务(service) 配置(Config) 一.egg框架介绍 简单来说 ...

  8. 第十一章 图形视图、动画和状态机框架——Qt

    一.图形视图框架的结构 图形视图框架提供了一个基于图形项的模型视图编程算法,主要由场景.视图和图形项三部分组成,这三部分分别由QGraphicsScence.QGraphicsView和 QGraph ...

  9. Qt知识回顾(十)——图形视图、动画和状态机框架

      Qt提供了图形视图框架(Graphics View Framework).动画框架(The Animation Framework)和状态机框架(The State Machine Framewo ...

最新文章

  1. 沾包 nagle算法等
  2. 使用django的用户帐号登录openfire
  3. mybatis,主键返回指的是返回到传入的对象中
  4. 为什么在子类中不重写超类的实例变量
  5. qq群 html,我的群组-普通群组.html
  6. SCVMM Self-Service Portal 2.0 SP1安装体验
  7. 我月薪3W,却不用熬夜加班做报表,这个养老工具,你一定要知道
  8. 必须重视针对SCADA系统的***
  9. adb命令查看手机上的APP包名和启动activity
  10. html轮播图代码自适应,【简易轮播代码】自适应全屏轮播banner图切换代码
  11. do while 循环 语法结构
  12. Windows 罕见技巧全集3
  13. readyState的值的含义
  14. linux系统怎么数据恢复,linux系统数据恢复
  15. java二维数组周边元素_求出二维数组主对角线、次对角线以及周边元素之和
  16. ThinkPad T480 Win10系统键盘失灵
  17. ubuntu使用xopen软件
  18. HTML基本知识点——图片标记
  19. R语言Bootstrap、百分位Bootstrap法抽样参数估计置信区间分析通勤时间和学生锻炼数据
  20. 如何查找文献及规范参考文献引用格式(以石家庄铁道大学图书馆为例)

热门文章

  1. 0319互联网新闻 | 网易云课堂和中国大学MOOC并入网易有道;快手上线快手概念版...
  2. Node.js 启动调试方式
  3. Oracle 11g Dataguard 物理备库配置(四)之broker snapshot standby测试
  4. java使用httpclient调用上传图片接口[示例]
  5. ubuntu/deepin 禁用IPV6
  6. 【01】Clean Code
  7. POJ-1364 King 差分约束
  8. 1-Dimensional Heightfield Visibility Query
  9. 王者服务器维护宝箱礼包都没领,王者荣耀:S19战令最后一天,还没领取奖励的玩家要注意了...
  10. ThreadLocal基本使用和内存泄漏分析