PDA

View Full Version : How to add a transition in onEntry in Qtstatemachine



andreahmed
17th April 2016, 16:46
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().

d_stranz
17th April 2016, 20:09
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.



// 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.

anda_skoa
17th April 2016, 22:56
@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,
_

d_stranz
17th April 2016, 23:17
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.

anda_skoa
18th April 2016, 09:22
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.

Good point.

I usually even have the signal object separate from the object containing the state machine, so that these "internal" signals are not part of the "external" API.

Cheers,
_

d_stranz
18th April 2016, 16:27
I usually even have the signal object separate from the object containing the state machine

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?

I guess I'm trying to understand how it would work in practice.

anda_skoa
18th April 2016, 16:43
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,
_