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?
-
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.
-
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!