State machines in Qt

State machines can be used for many purposes, but in this chapter we will only cover topics related to animation.

How to do it…

  1. First, we will set up a new user interface for our example program, which looks like this:
    How to do it…
  2. Next, we will include some headers in our source code:
    #include <QStateMachine>
    #include <QPropertyAnimation>
    #include <QEventTransition>
  3. After that, 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();
  4. Then, 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));
    
  5. 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);
  6. Next, add all the states we have just created to the state machine and define state 1 as the initial state. Then, call machine->start() to start running the state machine:
    machine->addState(s1);
    machine->addState(s2);
    
    machine->setInitialState(s1);
    machine->start();
  7. If you run the example program now, you will notice 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.
  8. 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);
  9. 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);

How it works...

There are two push buttons and a label on the main window layout. The button at the top-left corner will trigger the state change when pressed, while the label at the top-right corner will change its text to show which state we are currently in, and the button below will animate according to the current state.

The QEventTransition classes define what will trigger the transition between one state and another.

In our case, we want the state to change from state 1 to state 2 when the ui->changeState button (the one at the upper left) is clicked. After that, we also want to change from state 2 back to state 1 when the same button is pressed again. This can be achieved by creating another event transition class and setting the target state back to state 1. Then, add these transitions to their respective states.

Instead of just assigning the properties directly to the widgets, we tell Qt to use the property animation class to smoothly interpolate the properties toward the target values. It is that simple!

There is no need to set the start value and end value, because we have already called the assignProperty() function, which has automatically assigned the end value.

There's more…

The state machine framework in Qt provides classes for creating and executing state graphs. Qt's event system is used to drive the state machines, where transitions between states can be triggered by using signals, then the slots on the other end will be invoked by the signals to perform an action, such as playing an animation.

Once you understand the basics of state machines, you can use them to do other things as well. The state graph in the state machine framework is hierarchical. Just like the animation group in the previous section, states can also be nested inside of other states:

There's more…
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.54.136