所以我试图了解Qt的QStateMachine的一个问题,我希望有人可以帮助解释为什么会发生这种情况。我对QStateMachine的基本理解非常感兴趣,而不仅仅是修复。
首先考虑具有状态A,B和事件1的状态机。事件1将您从A带到B. A是初始状态。
具体来说,这是为了维护邻居。在设备X中,我收到一条消息,其中邻居Y说你好。这导致邻居X为这个新邻居Y malloc一个邻居状态机。这使得邻居状态机然后调用QStateMachine :: start();
现在,在启动此状态机之后,我需要继续处理此hello消息。所以起初我在做:
QStateMachine::start( ) ;
emit event 1 ;
我的理解是这不起作用,因为start是异步调用,因此状态机在启动完成之前不会处于初始启动状态。这引出了我的第一个问题。
1)因此,状态机启动被置于qapp事件队列中,但也不会发出异步调用?事件1不会在启动后被放置在事件队列中,所以这不意味着我们将处于初始状态吗?或者发出不是异步调用?
认为这是问题我通过将函数连接到状态机启动信号来稍微改变了我的代码。然后,如果状态机未启动,我将代码更改为队列事件,并在调用启动信号后处理此挂起事件队列(并将其发送到状态机)。
事实证明,当我开始发出信号时,初始状态仍未设置。例如QStateMachine :: configuration()。hastains(initialstate)== false。这引出了我的第二个更重要的问题。
2)为什么在发出启动信号时我不处于初始状态。
这里的事件顺序是:
序列应为:
或事件更好我希望我没有排队事件。我希望我能做到这一点:
答案 0 :(得分:6)
转换信号仅在状态更改后(QStateMachinePrivate::registerSignalTransition
中)连接且连接不是排队连接:
bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
signalEventGenerator->metaObject()->methodOffset());
对于要接收的“事件1”,机器必须已处于对该信号作出反应的状态。即使它是一个排队的连接,插槽也会排队,但只有在接收到信号后才会排队,但由于此时还没有连接,所以它不会排队。
要解决您的问题,您可以在发出信号之前等待机器处于“状态A”:
machine->start();
qApp->processEvents();
emit event1();
或者您可以延迟信号发射并在其他已经排队的操作之后将其排队:
machine->start();
QTimer::singleShot(0, emitter, SIGNAL(event1()));
// or
QMetaObject::invokeMethod(emitter, "event1", Qt::QueuedConnection);
在设置初始状态之前发出started
信号(根据源代码),如果在设置任何状态之前进行了初始化,这可能会有所帮助。如果您需要等待初始状态,可以使用信号QState::entered
。