Reading the statemachine in qt docs, they say you can override the onEntry() for each state. My question is how to add transistion inside the onEntry function so that the state machine moves to another state from the onEntry().
Printable View
Reading the statemachine in qt docs, they say you can override the onEntry() for each state. My question is how to add transistion inside the onEntry function so that the state machine moves to another state from the onEntry().
Create a new QSignalTransition instance and set its target state to the state you want to go to from the onEntry method. Create a new signal for your class to be used by the QSignalTransition. Add this new transition to the state with the onEntry function. In the onEntry function, emit the signal.
Code:
// MyStateMachine.h signals: void goToState2(); private slots: void onState1Entered(); void onState2Entered(); private: void setupStates(); private: QStateMachine * pStateMachine; //... // MyStateMachine.cpp void MyStateMachine::setupStates() { // pStateMachine is theQStateMachine instance QState * pState1 = new QState( pStateMachine ); connect( pState1, SIGNAL( entered() ), this, SLOT( onState1Entered() ) ); QState * pState2 - new QState( pStateMachine ); connect( pState2, SIGNAL( entered() ), this, SLOT( onState2Entered() ) ); QSignalTransition * pState1To2 = new QSignalTransition( this, SIGNAL( goToState2() ); pState1To2->setTargetState( pState2 ); pState1->addTransition( pState1To2 ); } void MyStateMachine::onState1Entered() { emit goToState2(); }
As you see, you do not have to create a custom QState and override the onEntry() method. Everything you want to do can almost always be done using standard QState and QStateMachine from the Qt libraries. The code I posted above is adapted from a complex state machine I implemented to handle mouse and keyboard events in a graphics plot. Even though I called the class "MyStateMachine" in this example, it is not derived from QStateMachine. It instantiates a QStateMachine instance ("pStateMachine ") and adds all of the states and transitions to that.
@d_stranz: unless the slot does more than just emit the signal you could have used the state's signal directly for the signal transition.
Cheers,
_
Yes, of course. But I think for debugging purposes it is clearer to understand what is happening if you have a handler for the slot where you can set a breakpoint and back trace how it got there. With the state machine I developed, it was complex enough that I often needed debug statements to be able to follow the state transitions, so I developed that convention I posted.
I'm not entirely sure I understand what you mean by this. I think what you are saying is that instead of having the class that holds the QStateMachine instance be the one that generates the state transition signals, you would implement another class to implement the signal methods. This class would have a private implementation. Would you make this class a friend of your "public" class so it could emit the signals or would you implement the state machine entirely within the private class?Quote:
I usually even have the signal object separate from the object containing the state machine
I guess I'm trying to understand how it would work in practice.
Taking your example, MyStateMachine would have another member of one (or more) classes that serve as signal sources for transitions, if I would like to add logging/break points as you suggested earlier or if the actual trigger needs to be a method call else where.
One example for the latter would be that you need to expose an object with callable methods to QML so that you can trigger statemachine transitions from there, but only want to expose a subset of such triggers.
Also applies to only exposing certain transition trigger functions/slots to certain widgets.
Cheers,
_