最近接触了SCXML这个状态描述文本,简单来讲就是描述了整个状态的变迁过程的一种XML格式的表格。Qt labs中有一个项目就是QScxml,它基于QStateMachine上层制作,可以直接读取SCXML格式的文件生成内部状态对象和成员,可以直接在Qt中进行状态变迁,十分方便。

先来简单介绍一下SCXML的格式,以

<scxml initial="FirstState" version="0.9" xmlns="http://www.w3.org/2005/07/scxml">

作为整个SCXML的开头,scxml标签旁的initial表示状态机启动之后进入的第一个初始化状态,在这里我写了FirstState,表示状态几一启动,就进入了FirstState.

<state id="FirstState" initial="FirstChildNode">

以state标签开头表示了状态的基本概念,其中的id是作为该状态的索引号给你之后写target进行索引,这个时候同学会看到又出现了一个initial,这时的FirstChildNode表示此时的FirstState并不是一个原子状态,而是一个组合状态的父状态。而FirstChildNode恰恰就是它的子状态。也就是说进入了FirstState之后,就会立即进入FirstChildNode,期间如果你调用了<onentry>和<onexit>标签,你会发现调用了多次,不必奇怪,其实你的状态是进入了一层一层中的最里层,每进一层就会调用<onentry>和<onexit>。

<transition event="Key.A" target="SecondState"></transition>
<transition event="Key.B" target="ThirdState"></transition>

又来新东西了,这个<transition>标签表示真正的事务处理过程,之后的event属性表示你传递给QScxml中的postNamedEvent(const QString)函数中的QString,所以我之前提过那个id的作用,就是全局的索引号,同时请注意:SCXML中默认的event是前缀查找,也就是说对于event="GameTest"来说,你输入"GameTest","Game","Game.","Game.*"效果是完全一样的,不过我试了下在QScxml中只有第一种和第三种有效(官方说明)。之后的<target>自然很好理解,就是你在这个状态下,经过了event事件,达到了target状态(target不能接收函数,必须是字符串状态变量而cond可以接收函数或者字符串)。例子中就表示无论你在FirstState中的哪个孩子中,只要你收到了Key.A事件,你都会跳出子状态乃至父状态,直接跳到对应的SecondState中去。注意:写在父状态中的translation是给它以及它的孩子全局共享的,如果你觉得你可能在孩子节点中对于某一个事件你不满意,你想要重写,那你完全可以在FirstChildNode中写下

<transition event="Key.A" target="FourhState"></transition>
<transition event="Key.B" target="FifthState"></transition>

这个时候状态机会优先处理最子层的事务处理,如果状态机发现在最子层并没有完成该事件(包括没有找到该translation和找到translation可是cond为false)都会将事件向上传递给父状态进行处理。

在来说说比较有用的标签<cond>,这个标签可以放在<translation>中也可以放在<if>中,当放在<translation中时>

<transition event="Key.A" target="FourhState" cond="isTrue"></transition>

表明当isTrue为true的时候,target才真正进行转移(在这里isTrue即可以是简单变量也可以是script函数来返回bool值),比较常用的用法有

<translation event="Key.A">
<if cond="isTrue()">
<script>FuncA()</script>
<elseif cond="isFalse()"/>
<script>FuncB()</script>
<else/>
<script>FuncC()</script>
</if>
</translation>

表明事件Key.A来的时候进行cond判断来调用相应的script。

另外我们也可以用到状态机在上而下处理事件的机制,来进行灵活的target动态转换工作.

<transition event="Key.A" target="A" cond="isTrue()" />
<transition event="Key.A" target="B" >

细心的你一定会发现,怎么两个translation的event一样。其实这种用法在W3C的examples中也提到过,因为状态机在上而下的处理机制,你可以在断言为false的时候有一个默认的target,而在true的时候进入你事先设定的target,可以非常灵活的使用这种机制进行判断.

另外介绍一下两个也比较重要的标签,在上文也提到过<onentry>和<onexit>,

<onentry>
<script>
enterState("A");
</script>
</onentry>
<onexit>
<script>
exitState("B");
</script>

表明在进入和退出该状态的时候自动触发的事件,这里默认调用的script,你可以很灵活的控制状态切换时应该需要的工作.

QScxml中有一个功能非常强大的函数

void QScxml::registerObject (QObject* o, const QString & name, bool recursive)

用它进行注册之后,你可以在SCXML的文件中写各种script function,比如你注册的时候m_scxml->registerObject(this, "Widget", true),这个时候你就可以在SCXML文件中写下

<script>
function show()
{
Widget.show();
 }
</script>

表明无论你在translation还是onentry还是onexit中的<script>标签写show()这个函数,你最终都会通过QScxml这个强大的类让你可以和它进行交互。如果你嫌写script function麻烦,

你也可以直接在<script>标签中写上

Widget.show();

一样可以直接运行。script function的强大不仅仅在于可以通过QScxml让你和你的对象进行交互,同时它也可以用来做断言cond判断,比如

function isTrue()
{
return Widget.isGood();
}

你可以非常灵活的实现你自己类的断言函数,配合之前的translation中的cond做到动态切换target,非常方便。

今天就简单介绍到这里,在开始接触SCXML的时候发现国内的资料很少,写这篇博文也当贡献自己的一份力了,更多的内容需要你自己去挖掘,希望你会喜欢这篇文章,留下你的脚印,给我支持,谢谢:)

SCXML和QScxml使用总结的更多相关文章

  1. scxml 图像展示器 (基于C++ MFC GDI tinyxpath的实现)

    以前的时候学习新东西没有总结的习惯,周末把以前研究的东西翻了翻,稍微总结下. Scxml是w3c出来的基于状态机的对话脚本语言标准,具体内容可以谷歌到,这里讲述自己开发的一个把scxml转化为可交互图 ...

  2. 【基础】Qt SCXML Calculator QML Example

    Qt SCXML Calculator QML Example 这个系统自带的例子原本主要是用来说明SCXML机制的,但是由于计算器的经典和简洁,我认为用来练习QML非常合适,原本的例子还有一些问题, ...

  3. java jar包收集

    activation~与javaMail有关的jar包,使用javaMail时应与mail.jar (mail.jar和activation.jar)一起加入到lib中去,具体负责mail的数据源和类 ...

  4. apache commons Java包简介

    更多信息,请参考:http://commons.apache.org/ 一.Commons BeanUtils说明:针对Bean的一个工具集.由于Bean往往是有一堆get和set组成,所以BeanU ...

  5. Apache Commons 简述

    Apache Commons 是一个关注于可复用的 Java 组件的 Apache 项目.Apache Commons 由三部分构成: Commons Proper - 一个可复用的 Java 组件库 ...

  6. 常见 jar包详解

        常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...

  7. Qt: The State Machine Framework 学习

    State Machine,即为状态机,是Qt中一项非常好的框架.State Machine包括State以及State间的Transition,构成状态和状态转移.通过状态机,我们可以很方便地实现很 ...

  8. Qt 状态机框架学习(没学会)

    Qt状态机框架是基于状态图XML(SCXML) 实现的.从Qt4.6开始,它已经是QtCore模块的一部分.尽管它本身是蛮复杂的一套东西,但经过和Qt的事件系统(event system).信号槽(s ...

  9. Qt状态机框架

    The State Machine Framework 状态机框架提供了用于创建和执行状态图的类.概念和符号是基于Harel的Statecharts: A visual formalism for c ...

随机推荐

  1. Qt入门(17)——组装复杂的控件

    下面是如何把两个窗口部件封装成一个新的组件.首先,我们使用一个自定义的窗口部件作为一个子窗口部件. #include <qapplication.h> #include <qpush ...

  2. JQuery固定表头插件fixedtableheader源码注释

    在开发XX车站信息系统时,需要将大量数据显示在一个巨大的表格内部,由于表格是一个整体,无法分页,加之数据很多,超出一屏,为了方便用户,决定使用固定表头的插件,经过测试,发现JQuery 插件:fixe ...

  3. 关于cocos2d这个东西

    我是在今年6月份左右接触到cocos2d这个东西的,当时就是想写个小游戏,结果买书的时候误打误撞就买了cocos2d的书. cocos2d是一个开源的游戏引擎,用于构建2d游戏,同时也可以用它写各种图 ...

  4. postgresql使用文档之一 初始化数据存储区

    17.2. 创建一个数据库集群(Database Cluster) 在你能做任何事情之前,你必须在磁盘上初始化一块存储空间.我们称这为一个数据库集群(database cluster). 一个Data ...

  5. UVALive 7148 LRIP 14年上海区域赛K题 树分治

    题意 n个点组成一棵树, 带有点权. 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D. 显然是树分治, 但是分治之后如何维护答案呢. 假设当前重心为g, 分别记录g出发不降路径的长度,以及 ...

  6. hdu 1698 线段树成段更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 #include <cstdio> #include <cmath> # ...

  7. Mysql binlog日志解析

    1. 摘要: Mysql日志抽取与解析正如名字所将的那样,分抽取和解析两个部分.这里Mysql日志主要是指binlog日志.二进制日志由配置文件的log-bin选项负责启用,Mysql服务器将在数据根 ...

  8. [置顶] Ajax程序:处理异步调用中的异常(使用Asp.Net Ajax内建的异常处理方法)

    无论在Window应用程序,还是Web应用程序以对用户友好的方式显示运行时的异常都是很有必要,尤其对于可能有很多不确定因素导致异常的Web应用程序;在传统的Web开发中,处理异常的方式——设计专门一个 ...

  9. 学习restful 架构

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  10. 1031. Hello World for U (20)

    题目链接:http://www.patest.cn/contests/pat-a-practise/1031 题目: 分析: 排版题.注意先计算好最后一排的字符数,然后计算前面几排的空格数.难度不大 ...