How to pass parameters between states of a QStateMachine



  • Hello,

    I was wondering, what is the proper way of passing parameters between states in a QStateMachine. The transitions between states are triggered by signals, but the signal parameters are not passed to the other QState - only entered() is emitted without options to specify some input data.
    One way I can think to solve the problem is to make QSignalTransition subclass, take the signal parameters in onTransition(QEvent* event) and set them to the targetState() using assignProperty() or some custom method of QState descendant.

    Is there some default solution from QStateMachine framework which I am missing?


  • Lifetime Qt Champion

    Hi,

    What kind of parameter are you thinking about ? On what kind of object would they work ?



  • QByteArray parameters. My task is to implement a network protocol working over TCP. I have a class SendMessage:public QState that wraps the state machine for sending a single message (transitions of the QTcpSocket for bytesWritten(), readyRead(), timeout()). I want to combine these states into higher level protocol state machine. When it leaves a state and enters another state it should pass what data it has received.


  • Lifetime Qt Champion

    Might be easier to have a central object that handles the network part and your state machine acts on it so you would be able to retrieve the information needed from that "central point"



  • Thanks for your feedback.
    I was trying to think of a more general solution that I may easily specialise to the different network sessions that I have to implement. I think that the result from one state to be passed as input to the next state as part of the transition is a more natural flow of the state machine (without some global state maintenance). I can implement it with by specialising QSignalTransition, I was just curious if there wasn't something ready made.



  • If anyone else worked on this aspect of state machines, would appreciate input - I'm wondering about the same issue.



  • For my problem, I did the following:
    Created a subclass of QState, that implements the virtual method QState::onEntry(...) where it takes the parameter from the signal (QByteArray in my case) and keeps it in a local member:

    @
    class ParamState : public QState
    {
    public:
    QByteArray data() {return mData;}
    protected:
    virtual void onEntry(QEvent* e);
    QByteArray mData;
    };

    void ParamState::onEntry(QEvent* e)
    {
    if (e->type() == QEvent::StateMachineSignal) {
    QStateMachine::SignalEvent* se = static_castQStateMachine::SignalEvent*(e);
    if (se->arguments().size() > 0) {
    QVariant arg = se->arguments().at(0);
    if (arg.canConvert(QMetaType.QByteArray))
    mData = arg.toByteArray();
    }
    }
    }
    @

    Each state in my state machine is ParamState instance. In the slots for the QState::entered signal I use the following:
    @
    ParamState* state = (ParamState*)sender();
    state->data() ... <--- the QByteArray that was passed to the state via the transition signal
    @



  • Thanks, this is a helpful example!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.