Qt 5.8如何将SCXML框架与子状态机一起使用?

时间:2017-01-31 13:58:36

标签: qt scxml

我正在尝试构建一个系统,该系统由主状态机编排,并为正在执行的任务配备不同的子状态机。作为一名长期的Qt用户,我在Qt 5.8中查看了新的SCXML实现。但是我无法弄清楚如何使用5.8提供的API来正确实现子状态机。

我的想法是使用主状态机,然后在主状态机的状态中调用特定的子状态机。在调用子状态机工作时,我无法弄清楚在顶级状态机对象发出invokedServicesChanged(..)之后如何访问它们我可以访问指向QScxmlInvokableService但不能访问相关状态机的指针。

此外,顶级状态机对象仅从顶部而不是从调用的状态机公开状态和事件。例如,topLevelStateMachine->activeStateNames()仅列出顶级状态。

查看Qt的源代码,我看到QScxmlInvokableService实际上是QScxmlScxmlService的基类,它包含指向相关状态机的指针。遗憾的是,QScxmlScxmlServiceqscxmlinvokableservice_p.h中定义,其中私有,因为名称中的_p表示。那我该如何使用公共SCXML API呢?我错过了什么吗? IIRC SCXML支持是5.7中的技术预览,但现在包含在5.8中作为正态分发的一部分。

1 个答案:

答案 0 :(得分:0)

我花了大约一周时间研究这些示例,然后编写自己的状态机和响应它的代码。由于文档不够清晰,因此需要一段时间。

我发现activeStateNames确实检索了状态机中包含的所有状态,包括子状态。

我花了几个traffic light example的读数来弄清楚这一点。关键是子状态机包含在特定状态中。 (状态机的图形视图在这里有帮助。)

在示例中,整体顶级计算机中只有两种状态:workingbroken。转换由事件smashrepair控制。

在这两个状态中的每一个都是较小的状态机。 Broken包含两种状态的状态机:blinkingunblinking。当输入blinking时,该状态机在状态broken开始。

blinking的子状态broken中,如果使用blinking(默认)或false和{{blinking调用,则activeStateNames将返回broken 1}}使用true调用时。

那你怎么用呢?

如果我想根据特定状态设置/取消设置,我可以在机器中connectToState。当状态在活动和非活动之间发生变化时,我连接到的插槽将被调用,并且它将接收一个布尔值,说明状态是否处于活动状态。在红绿灯示例中,状态red已连接到redLight。由于redLight处于red状态时应处于启用状态,否则它会连接到一个布尔值:true打开灯,false将其关闭。

好的,但如果我想在进入州时抓住一个事件怎么办?

我只需选择状态,然后添加onEntry - >发送并指定事件名称。这将导致在我进入状态时发送事件。可以使用connectToEvent将此事件路由到插槽(在Qt 5.8中)。 [Qt 5.7版本只有一个通用eventOccurred信号,您可以将其发送到插槽,然后使用event.name()查询哪个事件。]