Qt状态机学习3

                      在使用状态机表述的系统中中存在一个属性,这个属性取值都是是互相排斥的,比如电源有打开和关闭,灯有亮和灭,但是不一定只有两个取值。我们的理想状态机不可能只有一个单一的属性。

                      下面我们举一个例子,在一个状态机中存在下面这几种属性,每个属性都有几个取值。

                      

                       所以就会有四种状态,2*2 = 4;如果每个状态都是可以互相转换的饿,那么就是4*2 = 8中过渡。

                       如果又添加了一种属性

                        

                       那么就是2*2*3=12中状态,12*2 = 24中过渡,是指数级的增长,而且在添加和移除属性是,会影响状态。

                       在此Qt的QState类中有一个枚举类型

                      

                        第二个平行的状态集就是为了解决这个问题。

1#include <QApplication> 2#include <QState> 3#include <QStateMachine> 4#include <QPushButton> 5#include <QVariant> 6#include <QFinalState> 7#include <QLayout> 8#include <QHistoryState> 9#include <QLabel> 10#include <QMessageBox> 11#include <QtDebug> 12#include <QAbstractTransition> 13 14 15 16 17//Qt的状态机是层次的,是事件驱动的,使用到了事件循环,那么就是异步的 18int main(int argc, char* argv[]) 19{ 20 QApplication app(argc,argv); 21 22 QStateMachine sMachine;//一个状态机对象 23 QState s;//和fState在同一个层次 24 25 QState s0;//开始状态,空白状态 26 QState s1;//3个状态对象 27 s1.setChildMode(QState::ParallelStates); 28 s1.setParent(&s); 29 QState s2; 30 s2.setParent(&s); 31 QState s3; 32 s3.setParent(&s); 33 s.setInitialState(&s1);//一组状态中要指定一组状态中的初始状态 34 35 36 QState s11; 37 s11.setChildMode(QState::ExclusiveStates); 38 s11.setParent(&s1); 39 QState s111;//a1 40 s111.setParent(&s11); 41 QState s112;//a2 42 s112.setParent(&s11); 43 s11.setInitialState(&s111); 44 QState s12; 45 s12.setChildMode(QState::ExclusiveStates); 46 s12.setParent(&s1); 47 QState s121;//b1 48 s121.setParent(&s12); 49 QState s122;//b2 50 s122.setParent(&s12); 51 s12.setInitialState(&s121); 52 53 54 55 56 QHistoryState sh;//记录s组状态被打断的状态 57 sh.setParent(&s); 58 QFinalState fState; 59 60 QState is;//中断状态 61 62 QWidget w; 63 QHBoxLayout layout; 64 QPushButton button(QObject::tr("状态改变")); 65 QPushButton qButton; 66 QPushButton startButton("start"); 67 QPushButton stopButton("stop"); 68 qButton.setText(QObject::tr("退出")); 69 QPushButton iButton; 70 iButton.setText(QObject::tr("打断")); 71 72 QPushButton button1("a1,b1"); 73 QPushButton button2("a1,b2"); 74 QPushButton button3("a2,b1"); 75 QPushButton button4("a2,b2"); 76 77 QLabel showLabel; 78 QLabel showLabel2; 79 QLabel showLabel3; 80 layout.addWidget(&button); 81 layout.addWidget(&qButton); 82 layout.addWidget(&iButton); 83 layout.addWidget(&showLabel); 84 layout.addWidget(&showLabel2); 85 layout.addWidget(&showLabel3); 86 layout.addWidget(&startButton); 87 layout.addWidget(&stopButton); 88 layout.addWidget(&button1); 89 layout.addWidget(&button2); 90 layout.addWidget(&button3); 91 layout.addWidget(&button4); 92 w.setLayout(&layout); 93 94 95 QMessageBox box(&w); 96 box.addButton(QMessageBox::Ok); 97 box.setText(QObject::tr("打断了,现在是is")); 98 box.setIcon(QMessageBox::Information); 99 100 s0.addTransition(&button,SIGNAL(clicked()),&s); 101 102 s1.addTransition(&button,SIGNAL(clicked()),&s2);//s1为这个过渡的始状态,s2为末状态 103 104 //八个过渡,可是应为选择的是2个属性,所以是2+2和2*2一样,但是这样是线性的 105 //比如按钮3被点击,s111和s122都是activity的同时响应,平行的 106 s111.addTransition(&button3,SIGNAL(clicked()),&s112);//a1->a2 107 s111.addTransition(&button4,SIGNAL(clicked()),&s112); 108 s112.addTransition(&button1,SIGNAL(clicked()),&s111);//a2->a1 109 s112.addTransition(&button2,SIGNAL(clicked()),&s111); 110 111 s121.addTransition(&button2,SIGNAL(clicked()),&s122);//b1->b2 112 s121.addTransition(&button4,SIGNAL(clicked()),&s122); 113 s122.addTransition(&button1,SIGNAL(clicked()),&s121);//b2->b1 114 s122.addTransition(&button3,SIGNAL(clicked()),&s121); 115 116 s2.addTransition(&button,SIGNAL(clicked()),&s3); 117 s3.addTransition(&button,SIGNAL(clicked()),&s1); 118 119 //每个状态进入时,设置指定对象指定项指定的值 120 s1.assignProperty(&showLabel,"text","当前:s1"); 121 s2.assignProperty(&showLabel,"text","当前:s2"); 122 s3.assignProperty(&showLabel,"text","当前:s3"); 123 124 //同时进入,而且这个是原子操作,不会被事件打断,但是是队列的,因为状态机是单线程的 125 s11.assignProperty(&showLabel,"text","s11"); 126 s12.assignProperty(&showLabel2,"text","s12"); 127 128 s111.assignProperty(&showLabel,"text","a1"); 129 s112.assignProperty(&showLabel,"text","a2"); 130 s121.assignProperty(&showLabel2,"text","b1"); 131 s122.assignProperty(&showLabel2,"text","b2"); 132 133 134 135 //给每个状态添加过渡 136 s.addTransition(&qButton,SIGNAL(clicked()),&fState);//s -- > finalState,但是在这组内的状态对于这个过渡可以覆盖 137 138 //s2.addTransition(&qButton,SIGNAL(clicked()),&s3);//如果添加这一个句,那么在s2点击qButton按钮 139 //就不会退出,只是转向了s3 140 141 s.addTransition(&iButton,SIGNAL(clicked()),&is); 142 143 is.addTransition(&sh); 144 145 146 QObject::connect(&is,SIGNAL(entered()),&box,SLOT(exec())); 147 148 149 150 151 //也可能重写 QAbstractState::onEntry()和QAbstractState::onExit()函数 152 //在UML的状态图中,每个状态在进入状态和离开状态的时候都会进行相关的操作 153 //这个可以通过这两个信号来解决,也可通过继承来重写上述的两个函数 154 QObject::connect(&s3,SIGNAL(entered()),&w,SLOT(showMinimized())); 155 QObject::connect(&s3,SIGNAL(exited()),&w,SLOT(showMaximized())); 156 QObject::connect(&sMachine,SIGNAL(finished()),&app,SLOT(quit())); 157 158 QObject::connect(&startButton,SIGNAL(clicked()),&sMachine,SLOT(start())); 159 QObject::connect(&stopButton,SIGNAL(clicked()),&sMachine,SLOT(stop())); 160 161 sMachine.addState(&s0); 162 sMachine.addState(&s);//对于状态机只是添加顶层的状态 163 // sMachine.addState(&s1); 164 // sMachine.addState(&s2); 165 // sMachine.addState(&s3); 166 sMachine.addState(&fState); 167 sMachine.addState(&is); 168 169 170 //设置状态机的初始状态 171 //sMachine.setInitialState(&s1); 172 sMachine.setInitialState(&s0);//对于状态机的初始化,只是使用顶层的状态初始化,所以每个顶层如果是 173 //一组状态,那么就要指定这组状态的初始化状态 174 w.show(); 175 //状态机开启 176 // sMachine.start(); 177 178 //可以通过给状态分组来实现状态过渡的共享,比如我们希望在任何状态下我们都能够退出, 179 //那么这个退出状态就是比其他的状态具有高的状态层次,那么我们就要将其他的状态封装在 180 //合适的与退出状态同层次的一个高阶的状态层次中 181 return app.exec(); 182}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid

Twitter的分布式自增ID算法snowflake (Java版)

概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移

UDT协议实现分析——UDT初始化和销毁

UDT协议是一个用于在高速Internet上传输大量数据的基于UDP的可靠传输协议。我们可以将UDT协议的实现看作一个比较复杂的状态机。更准确的说,是一个主状态机,外加多个子状态机。主状态机是指协议实现中全局唯一、全局共享的状态与数据结构,主要对应于CUDTUnited类。子状态机则是对于一次UDT连接或一个Listening的UDTServer的抽象