文章目录

  • 介绍
  • QState函数说明
  • QHistoryState
  • 函数使用说明

介绍

​ 状态机,就是负责执行各种状态的切换。Qt状态机的使用场景主要针对比较复杂的界面,或者需要切换不同状态的控件

QT中对于状态机框架的介绍:(QT手册中的The State Machine Framework)

状态机框架提供了创建和执行状态图的一些类.这些概念和表示都是基于Harel状态图中的一些概念和记法.它也是UML状态图表的基础.状态机执行的语义是基于状态图XML(SCXML).

状态图提供了一种图形化的方式来对一个系统建模,从而反映它怎么响应外部触发.这是通过定义系统可能进入的一些状态以及系统怎么从一个状态转换到另一个状态(不同状态之间转变)来实现的.事件驱动系统的一个关键的特征(例如Qt应用程序)就是行为通常不仅取决于上次或当前事件,还取决于在它之前的一些事件.用状态图,这个信息非常容易表达.

状态机框架提供了一套API以及一种执行模型,可有效地将状态图的元素和语义嵌入到Qt应用程序当中.该框架与Qt的元对象系统结合紧密:例如,不同状态之间的转变可由信号触发且状态可配置用于设置QObject的属性和方法.Qt的事件系统用于驱动状态机.

状态机框架中的状态图是分层的.状态可嵌套在另一个状态内.状态机的当前配置包含一些当前活跃的状态.状态机中的一个有效的配置中的所有状态都有一个共同的祖先.

qt提供了这些类来创建事件驱动的状态机.状态是单线程异步执行的

class description
QAbstractState The base class of states of a QStateMachine(状态机的基类)
QAbstractTransition The base class of transitions between QAbstractState objects(状态转换的基类)
QEventTransition QObject-specific transition for Qt events(事件转变)
QFinalState Final state(终止状态)
QHistoryState Means of returning to a previously active substate(历史状态)
QKeyEventTransition Transition for key events(按键事件转变)
QMouseEventTransition Transition for mouse events(鼠标事件转变)
QSignalTransition Transition based on a Qt signal(信号转变)
QState General-purpose state for QStateMachine(状态机状态类)
QStateMachine Hierarchical finite state machine(提供了分层的有限状态机)
QStateMachine::SignalEvent Represents a Qt signal event(截获某一信号时触发)
QStateMachine::WrappedEvent Holds a clone of an event associated with a QObject(发生状态转变时触发)
Protected Functions
virtual bool event(QEvent *e) override
virtual void onEntry(QEvent *event) override
virtual void onExit(QEvent *event) override

QState函数说明

  1. QState::assignProperty()函数可用于当进入某个状态时设置某个QObject的一个属性(详细属性名可从Q_PROPERTY中查找)

  2. QState::addTransition()函数用于添加与给定发送者对象的给定信号关联的转换,并返回新的QSignalTransition对象

  3. 当进入某个状态时,就会发出QState::entered()信号.当离开这个状态时,就会发出QState::exited()信号

  4. 为了使一个状态机能够完成,它需要拥有一个顶层的最终状态(QFinalState对象).当状态机进入一个顶层最终状态时,该状态机将会释放QStateMachine::finished()信号并停止.一个孩子状态可为最终状态(一个QFinalState对象)。当进入最终状态时,父状态发出QState::finished()信号。

  5. QState::ChildMode [ExclusiveStates,ParallelStates]

    Constant Description
    QState::ExclusiveStates 子状态是互斥的,必须通过调用QState::setInitialState()来设置初始状态
    QState::ParallelStates 子状态是平行的,当父状态被输入时,它的所有子状态将被并行输入;不需要设置初始状态

QHistoryState

QHistoryState::HistoryType

Constant Description
QHistoryState::ShallowHistory 默认值,只记录父状态的直接子状态。在这种情况下,以history状态为目标的转换将以父对象上次退出时的直接子状态结束。
QHistoryState::DeepHistory 记录嵌套状态。在这种情况下,以历史记录状态作为目标的转换最终将处于父元素上次退出时嵌套最深的子代状态。

函数使用说明

//保存s1的直接子状态
QHistoryState *s1h = new QHistoryState(s1);
QState *s3 = new QState();
s3->assignProperty(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(s1h);
machine.addState(s3);
s1->addTransition(interruptButton, SIGNAL(clicked()), s3);

在进入s3时显示一个信息框,然后通过历史状态立即返回到s1之前的孩子状态中

QStateMachine*s3 = new QStateMachine();
QState* s1 = new QState(QState::ExclusiveStates);//互斥状态
QState* s2 = new QState(QState::ExclusiveStates);
//设置背景色属性
s1->assignProperty(ui.pushButton, "styleSheet", "background-color:rgb(255,0,0)");
s1->assignProperty(ui.pushButton_2, "styleSheet", "background-color:rgb(0,255,0)");s2->assignProperty(ui.pushButton_2, "styleSheet", "background-color:rgb(255,0,0)");
s2->assignProperty(ui.pushButton, "styleSheet", "background-color:rgb(0,255,0)");QState* s11 = new QState(s1);
QState* s12 = new QState(s1);
s11->assignProperty(ui.pushButton_4, "styleSheet", "background-color:rgb(255,0,0)");
s11->assignProperty(ui.pushButton_5, "styleSheet", "background-color:rgb(0,255,0)");s12->assignProperty(ui.pushButton_5, "styleSheet", "background-color:rgb(255,0,0)");
s12->assignProperty(ui.pushButton_4, "styleSheet", "background-color:rgb(0,255,0)");
//当this发出sig_pushbutton_4()信号时,状态由s11切换到s12
s11->addTransition(this, SIGNAL(sig_pushbutton_4()), s12);
//当this发出sig_pushbutton_5()信号时,状态由s12切换到s11
s12->addTransition(this, SIGNAL(sig_pushbutton_5()), s11);
//当this发出sig_pushbutton()信号时,状态由s1切换到s2
s1->addTransition(this, SIGNAL(sig_pushbutton()), s2);
//当this发出sig_pushbutton_2()信号时,状态由s2切换到s1
s2->addTransition(this, SIGNAL(sig_pushbutton_2()), s1);
//将状态添加到状态机
s3->addState(s1);
s3->addState(s2);
s1->setInitialState(s11);
//由于状态为互斥状态,此处应设置初始状态
s3->setInitialState(s1);
//状态机启动
s3->start();

状态机状态转换:s3为状态机,s1、s2为顶级状态,s11、s12都为继承于s1的次级状态,所以当只有s1处于active状态时,s11、s12才会处于active状态

 QFinalState *state1 = new QFinalState(s1);s12->addTransition(this, SIGNAL(sig_pushbutton_5()), state1);s1->addTransition(s1, SIGNAL(finished()), s2);

实例化一个继承于s1的终止状态state1,当this发送sig_pushbutton_5()信号时,状态从s12切换到state1,此时s1会发出finished()

当addTransition没有转变目标时为无目标转变,无目标的转变可与其他转变一样的方式被触发;不同之处在于当无目标转变被触发时,它不会造成任何状态的改变。这可以允许你在当状态机处于某个特定状态时,对信号或事件作出响应而不用离开那个状态。

QState状态机使用详解相关推荐

  1. Kafka源码分析10:副本状态机ReplicaStateMachine详解 (图解+秒懂+史上最全)

    文章很长,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈 奉上以下珍贵的学习资源: 免费赠送 经典图书:<Java高并发核心编程(卷1)> 面试必备 + 大厂必备 +涨薪 ...

  2. 状态机思路在嵌入式开发中的应用详解

    关注.星标公众号,直达精彩内容 ID:技术让梦想更伟大 整理:李肖遥 状态机的概念 状态机是软件编程中的一个重要概念.比这个概念更重要的是对它的灵活应用.在一个思路清晰而且高效的程序中,必然有状态机的 ...

  3. Unity动画系统详解10:子状态机是什么?

    摘要:除了使用Layer还有没有更好的组织状态的方式呢?感觉一个Layer里面状态多的时候,还是很显得很乱. 洪流学堂,让你快人几步.你好,我是跟着大智学Unity的萌新,我叫小新,这是复(yu)习( ...

  4. PD快充DRP-TypeC连接状态机详解

    TypeC连接状态机详解 之前的文章已经铺垫了我们需要了解得一些基本得TypeC接口规范内容,并附图TypeC整个连接过程,状态得变化和定义: 今天详细说明TypeC在DRP的情况下,是如果实现连接, ...

  5. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4地面站立动作状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

  6. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4 主状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

  7. 万字长文详解如何用Python玩转OpenGL | CSDN 博文精选

    作者 | 天元浪子 来源 | CSDN博文精选 [编者按]OpenGL(开放式图形库),用于渲染 2D.3D 矢量图形的跨语言.跨平台的应用程序编程接口,C.C++.Python.Java等语言都能支 ...

  8. 【ES6】Generator函数详解

    [ES6]Generator函数详解 一.Generator函数简介 基本概念 函数写法 yield关键字介绍 二.next方法的参数 三.for...of循环 四.关于普通throw()与Gener ...

  9. 用netstat查看网络状态详解

    --用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态:                     ...

最新文章

  1. 中矿大新生赛 A 求解位数和【字符串】
  2. ubuntu下配置华为交换机s2016
  3. nefu 118 n!后面有多少个0 算数基本定理,素数分解
  4. 【产品】腾讯产品经理总结:toB的产品经理和toc产品经理区别
  5. 2019年python就业前景_2019年Python数据挖掘就业前景前瞻
  6. gulp与grunt对比
  7. 最长回文子串 C++
  8. 小学音乐教学和计算机的融合,小学学科教学与计算机深度融合赛课心得体会(共4篇)...
  9. 实现线程安全的单例模式的四种方式
  10. Java虚拟机------JVM内存区域
  11. select count(*) from返回值_MySQL 优化:count(1)真的比count(*)快吗
  12. 苹果 macOS Monterey 桌面抽象风格不好看,如何换成自己喜欢的照片?
  13. uni-app 自适应各种机型状态栏
  14. Rational Rose 2007安装使用教程
  15. 高德sdk android加载3857,GCJ02-Correct
  16. 跟极限编程创始人Kent Beck学编程
  17. 性能之颠-应用程序性能技术
  18. 有什么蓝牙耳机好用又不贵?适合学生党的平价蓝牙耳机推荐
  19. YAPI简单使用教程
  20. php 给视频添加水印,记php调用ffmpeg给视频加文字水印

热门文章

  1. 基于51单片机的数字电子钟万年历闰年判断闹钟设计
  2. 增加外链的优势和注意事项
  3. Qt5入门学习——模型/视图结构
  4. PCSX2和GSDX的源代码地址,通过SVN下载。
  5. 数仓工具—Hive进阶之谓词下推(12)
  6. List转String的几种方式
  7. ECharts地图api
  8. 领域驱动设计在爱奇艺打赏业务的实践
  9. Hoops API参考: 3D Graphics System的Flush_Contents()函数
  10. tinder的定位在哪_我重新设计了Tinder。 这是我在此过程中学到的。