My problem is the following: I need to create class, which contains QStateMachine instance. This class should have slots through which you could "ask" state machine to make transition to another state. And if transition was successful, my class should emit signal about it. How would I implement this? Class should have ability to emit certain signals according to certain slot invoke. Here is a small example of class:
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0)
{
mStateMachine = new QStateMachine(this);
QState *s1 = new QState(mStateMachine);
QState *s2 = new QState(mStateMachine);
QState *s3 = new QState(mStateMachine);
s1->addTransition(); // Transition to s2
s2->addTransition(); // Transition to s3
s3->addTransition(); // Transition to s1
mStateMachine->setInitialState(s1);
mStateMachine->start();
}
signals:
toS1();
toS2();
toS3();
public slots:
slotToS1()
{
/* post event to state machine about
transition to state s1,
if transition was successful,
then emit toS1() signal. */
};
slotToS2(){ /* Similar to slotToS1 */};
slotToS3(){ /* Similar to slotToS1 */};
private:
QStateMachine *mStateMachine;
}
I would be very grateful for your help!
UPD:
The slots are representing defferent kinds of transitions, so that outer class (that will be using MyClass
) could 'ask' for some transition. So, the slot send event or signal to state machine, it looks on event or signal and (if in right state) makes this transition. And I want to notify outer class with certain signal, that asked before slot (transition) was made successfuly.
To transition on a slot call, you need to somehow bind the slot to a
QAbstractTransition
. There are two ways of doing it:Use a
QEventTransition
and send a relevant event to trigger it.Use a
QSignalTransition
and use an internal signal to trigger it.To emit signals on state transitions, you can connect the
QAbstractTransition::triggered
orQState::entered
orQState::exited
signals to other signals. Remember, in Qt a connection target can be either a slot or a signal.Thus, using signal transitions:
Using event transitions is a bit harder, since the events you're using must be cloneable by the state machine. The core module's state machine only knows how to clone the
None
andTimer
events - see itscloneEvent
implementation.The widgets module adds support for various GUI/Widgets events - see the
cloneEvent
implementation there. You could, in a pinch, use such GUI events for your own purposes - after all, they are sent to a plainQObject
that doesn't interpret them in a special way.You can provide your own
cloneEvent
implementation that links with the others.I have had the same problem in the past and I have found the easiest way was to inherit fom QState with your own QState class and implement 2 methods called QState::onEntry(QEvent * event) QState::onExit(QEvent * event)
This way you are able to emit any signal you like when you exit and when you enter a new state.
Here is and example:
file mystate.h
And file mystate.cpp