QStateMachine父状态信号过渡被子状态覆盖 如何同时触发两类响应?
问题根因
QStateMachine 的过渡匹配默认采用贪心终止规则:当信号触发时,会从当前激活的最底层子状态开始向上查找匹配的过渡,找到第一个匹配项后就会停止向上遍历,且默认不会触发上层状态的同匹配条件过渡。你当前的场景中child1的专属过渡匹配成功,所以父状态的通用过渡没有被触发。
最优实现方案
仅需要给child1的专属过渡开启事件向上传播属性即可,仅一行代码修改就能满足需求,不需要调整原有逻辑结构,也不需要修改业务回调:
QSignalTransition* specificTransition = new QSignalTransition(&myStruct, &MyStruct::mySignal); specificTransition->setPropagateEvents(true); // 新增此行,开启过渡事件向上传播 child1->addTransition(specificTransition); connect(specificTransition, &QAbstractTransition::triggered, &myStruct, &MyStruct::specificResponse);
该方案的优势:
- 完全符合需求约束:不需要重复定义
MyStruct::mySignal信号,不需要在specificResponse中手动调用commonResponse - 代码改动量极小,原有逻辑层次完全保留,可读性和可维护性高
- 基于Qt框架原生特性实现,无自定义hack逻辑
可选兼容方案
如果你的场景中通用过渡和专属过渡需要跳转至不同的目标状态,也可以把业务逻辑和过渡跳转拆分实现:
// 通用逻辑绑定:仅当父状态及其子状态激活时触发 connect(&myStruct, &MyStruct::mySignal, parent, [&](){ if (parent->isActive()) { myStruct.commonResponse(); } }); // 专属逻辑绑定:仅当child1激活时触发 connect(&myStruct, &MyStruct::mySignal, child1, [&](){ if (child1->isActive()) { myStruct.specificResponse(); } }); // 保留你需要的过渡跳转逻辑即可,不需要在transition的triggered中绑定业务回调
内容的提问来源于stack exchange,提问作者co2fgtr
相关产品推荐
相关产品推荐

