我正在尝试构建一个系统,该系统由主状态机编排,并为正在执行的任务配备不同的子状态机。作为一名长期的Qt用户,我在Qt 5.8中查看了新的SCXML实现。但是我无法弄清楚如何使用5.8提供的API来正确实现子状态机。
我的想法是使用主状态机,然后在主状态机的状态中调用特定的子状态机。在调用子状态机工作时,我无法弄清楚在顶级状态机对象发出invokedServicesChanged(..)
之后如何访问它们我可以访问指向QScxmlInvokableService
但不能访问相关状态机的指针。
此外,顶级状态机对象仅从顶部而不是从调用的状态机公开状态和事件。例如,topLevelStateMachine->activeStateNames()
仅列出顶级状态。
查看Qt的源代码,我看到QScxmlInvokableService
实际上是QScxmlScxmlService
的基类,它包含指向相关状态机的指针。遗憾的是,QScxmlScxmlService
在qscxmlinvokableservice_p.h
中定义,其中私有,因为名称中的_p
表示。那我该如何使用公共SCXML API呢?我错过了什么吗? IIRC SCXML支持是5.7中的技术预览,但现在包含在5.8中作为正态分发的一部分。
答案 0 :(得分:0)
我花了大约一周时间研究这些示例,然后编写自己的状态机和响应它的代码。由于文档不够清晰,因此需要一段时间。
我发现activeStateNames确实检索了状态机中包含的所有状态,包括子状态。
我花了几个traffic light example的读数来弄清楚这一点。关键是子状态机包含在特定状态中。 (状态机的图形视图在这里有帮助。)
在示例中,整体顶级计算机中只有两种状态:working
和broken
。转换由事件smash
和repair
控制。
在这两个状态中的每一个都是较小的状态机。 Broken包含两种状态的状态机:blinking
和unblinking
。当输入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()查询哪个事件。]