State machine is not that hard to achieve in Qt at all. Let's get started by following these steps:
- We will set up a new user interface for our example program, which looks like this:
- We will include some headers in our source code:
#include <QStateMachine>
#include <QPropertyAnimation>
#include <QEventTransition>
- In our main window's constructor, add the following code to create a new state machine and two states, which we will be using later:
QStateMachine *machine = new QStateMachine(this);
QState *s1 = new QState();
QState *s2 = new QState();
- We will define what we should do within each state, which, in this case, will be to change the label's text, as well as the button's position and size:
QState *s1 = new QState();
s1->assignProperty(ui->stateLabel, "text", "Current state: 1");
s1->assignProperty(ui->pushButton, "geometry", QRect(50, 200, 100, 50));
QState *s2 = new QState();
s2->assignProperty(ui->stateLabel, "text", "Current state: 2");
s2->assignProperty(ui->pushButton, "geometry", QRect(200, 50, 140, 100));
- Once you are done with that, let's proceed by adding event transition classes to our source code:
QEventTransition *t1 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t1->setTargetState(s2);
s1->addTransition(t1);
QEventTransition *t2 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t2->setTargetState(s1);
s2->addTransition(t2);
- Add all of the states we have just created to the state machine and define state 1 as the initial state. Then, call machine->start() to run the state machine:
machine->addState(s1);
machine->addState(s2);
machine->setInitialState(s1);
machine->start();
- If you run the example program now, you will notice that everything works fine, except the button is not going through a smooth transition and it simply jumps instantly to the position and size we set previously. This is because we have not used a property animation to create a smooth transition.
- Go back to the event transition step and add the following lines of code:
QEventTransition *t1 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t1->setTargetState(s2);
t1->addAnimation(new QPropertyAnimation(ui->pushButton, "geometry"));
s1->addTransition(t1);
QEventTransition *t2 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t2->setTargetState(s1);
t2->addAnimation(new QPropertyAnimation(ui->pushButton, "geometry"));
s2->addTransition(t2);
- You can also add an easing curve to the animation to make it look more interesting:
QPropertyAnimation *animation = new QPropertyAnimation(ui->pushButton, "geometry");
animation->setEasingCurve(QEasingCurve::OutBounce);
QEventTransition *t1 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t1->setTargetState(s2);
t1->addAnimation(animation);
s1->addTransition(t1);
QEventTransition *t2 = new QEventTransition(ui->changeState, QEvent::MouseButtonPress);
t2->setTargetState(s1);
t2->addAnimation(animation);
s2->addTransition(t2);