I’m having some trouble with the Qt State Machine. I’m never able to execute the states: I get various types of errors and I can’t figure out what is the problem. Please see below for more information on the errors and the code that leads to them.
This is my main function:
int main(int argc, char *argv[])
{
// Initialize the app
// ... app initialization here
QApplication app(argc, argv);
// Create the state machine
QStateMachine machine;
MyState* ms1 = new MyState("ms1");
MyState* ms2 = new MyState("ms2");
QFinalState* fs = new QFinalState();
ms1->addTransition(ms2);
ms2->addTransition(fs);
machine.addState(ms1);
machine.addState(ms2);
machine.addState(fs);
machine.setInitialState(ms1);
QObject::connect(&machine, SIGNAL(finished()), new Finisher(), SLOT(OnFinished()));
machine.start();
return app.exec();
}
I set break points in MyState, but the break points never get hit and the start/stop methods never execute (I actually only expect start to be called). The application goes directly into the Finisher::OnFinished method.
Here is my state class:
class MyState: public QState
{
Q_OBJECT
private:
QString _stateName;
public:
MyState(QString stateName, QState * parent = 0):QState(parent), _stateName(stateName){}
~MyState(){}
public slots:
void start()
{
qDebug() << _stateName << " start.";
emit finished();
}
void stop()
{
qDebug() << _stateName << " stop.";
}
signals:
void finished();
//void exited();
};
The Finisher is pretty simple:
class Finisher:public QObject
{
Q_OBJECT
public slots:
void OnFinished()
{
qDebug() << "Finished!";
QTimer::singleShot(0, QApplication::instance(), SLOT(quit()));
}
};
I’ve tried several things, including setting the parent of each state directly:
// If I use the following code, I get an error
// stating that "the state has already been added to this machine"
MyState* ms1 = new MyState("ms1");
MyState* ms2 = new MyState("ms2", ms1);
QFinalState* fs = new QFinalState(ms2);
ms1->addTransition(ms2);
ms2->addTransition(fs);
machine.addState(ms1);
machine.addState(ms2);
machine.addState(fs);
machine.setInitialState(ms1);
// .. and so on
However, when it seems that I can’t add the states when the machine.addState is called:
QStateMachine::addState: state has already been added to this machine
QStateMachine::addState: state has already been added to this machine
Unrecoverable error detected in running state machine: Missing initial state in
compound state ''
I’ve also tried just leaving the constructors and not calling machine.addState:
QStateMachine machine;
MyState* ms1 = new MyState("ms1");
MyState* ms2 = new MyState("ms2", ms1);
QFinalState* fs = new QFinalState(ms2);
ms1->addTransition(ms2);
ms2->addTransition(fs);
machine.setInitialState(ms1);
// .. and so on
However, in this case I get the following errors:
QState::setInitialState: state 0xa05e5e0 is not a child of this state (0x43fe94)
QStateMachine::start: No initial state set for machine. Refusing to start.
The last one is strange because I explicitly state the initial state to ms1 and then I call start, so I don’t know what’s the problem there. Does anybody have any ideas on how to get this example to work?
There is nothing like
start()slot inQState– but it exists inQStateMachine.I suppose you want to reimplement
methods:
which is working just fine.