| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example animation/moveblocks |
| \title Move Blocks Example |
| |
| \brief The Move Blocks example shows how to animate items in a |
| QGraphicsScene using a QStateMachine with a custom transition. |
| |
| \image moveblocks-example.png |
| |
| The example animates the blue blocks that you can see in the image |
| above. The animation moves the blocks between four preset positions. |
| |
| The example consists of the following classes: |
| |
| \list |
| \li \c StateSwitcher inherits QState and can add |
| \c {StateSwitchTransition}s to other states. |
| When entered, it will randomly transition to one of these |
| states. |
| \li \c StateSwitchTransition is a custom transition that |
| triggers on \c{StateSwitchEvent}s. |
| \li \c StateSwitchEvent is a QEvent that triggers \c{StateSwitchTransition}s. |
| \li \c QGraphicsRectWidget is a QGraphicsWidget that simply |
| paints its background in a solid \l{Qt::}{blue} color. |
| \endlist |
| |
| The blocks are instances of \c QGraphicsRectWidget and are |
| animated in a QGraphicsScene. We do this by building a state |
| graph, which we insert animations into. The graph is then executed |
| in a QStateMachine. All this is done in \c main(). |
| Let's look at the \c main() function first. |
| |
| \section1 The \c main() Function |
| |
| After QApplication has been initialized, we set up the |
| QGraphicsScene with its \c{QGraphicsRectWidget}s. |
| |
| \snippet animation/moveblocks/main.cpp 1 |
| |
| After adding the scene to a QGraphicsView, it is time to build the |
| state graph. Let's first look at a statechart of what we are |
| trying to build. |
| |
| \image move-blocks-chart.png |
| |
| Note that the \c group has seven sub states, but we have only |
| included three of them in the diagram. The code that builds this |
| graph will be examined line-by-line, and will show how the graph |
| works. First off, we construct the \c group state: |
| |
| \snippet animation/moveblocks/main.cpp 2 |
| |
| The timer is used to add a delay between each time the blocks are |
| moved. The timer is started when \c group is entered. As we will |
| see later, \c group has a transition back to the \c StateSwitcher |
| when the timer times out. \c group is the initial state in the |
| machine, so an animation will be scheduled when the example is |
| started. |
| |
| \snippet animation/moveblocks/main.cpp 3 |
| \dots |
| \snippet animation/moveblocks/main.cpp 4 |
| |
| \c createGeometryState() returns a QState that will set the |
| geometry of our items upon entry. It also assigns \c group as the |
| parent of this state. |
| |
| A QPropertyAnimation inserted into a transition will use the |
| values assigned to a QState (with QState::assignProperty()), i.e., |
| the animation will interpolate between the current values of the |
| properties and the values in the target state. We add animated |
| transitions to the state graph later. |
| |
| \snippet animation/moveblocks/main.cpp 5 |
| |
| We move the items in parallel. Each item is added to \c |
| animationGroup, which is the animation that is inserted into the |
| transitions. |
| |
| \snippet animation/moveblocks/main.cpp 6 |
| |
| The sequential animation group, \c subGroup, helps us insert a |
| delay between the animation of each item. |
| |
| \snippet animation/moveblocks/main.cpp 7 |
| \dots |
| \snippet animation/moveblocks/main.cpp 8 |
| |
| A StateSwitchTransition is added to the state switcher |
| in \c StateSwitcher::addState(). We also add the animation in this |
| function. Since QPropertyAnimation uses the values from the |
| states, we can insert the same QPropertyAnimation instance in all |
| \c {StateSwitchTransition}s. |
| |
| As mentioned previously, we add a transition to the state switcher |
| that triggers when the timer times out. |
| |
| \snippet animation/moveblocks/main.cpp 9 |
| |
| Finally, we can create the state machine, add our initial state, |
| and start execution of the state graph. |
| |
| \section2 The \c createGeometryState() Function |
| |
| In \c createGeometryState(), we set up the geometry for each |
| graphics item. |
| |
| \snippet animation/moveblocks/main.cpp 13 |
| |
| As mentioned before, QAbstractTransition will set up an animation |
| added with \l{QAbstractTransition::}{addAnimation()} using |
| property values set with \l{QState::}{assignProperty()}. |
| |
| \section1 The StateSwitcher Class |
| |
| \c StateSwitcher has state switch transitions to each \l{QState}s |
| we created with \c createGeometryState(). Its job is to transition |
| to one of these states at random when it is entered. |
| |
| All functions in \c StateSwitcher are inlined. We'll step through |
| its definition. |
| |
| \snippet animation/moveblocks/main.cpp 10 |
| |
| \c StateSwitcher is a state designed for a particular purpose and |
| will always be a top-level state. We use \c m_stateCount to keep |
| track of how many states we are managing, and \c m_lastIndex to |
| remember which state was the last state to which we transitioned. |
| |
| \snippet animation/moveblocks/main.cpp 11 |
| |
| We select the next state we are going to transition to, and post a |
| \c StateSwitchEvent, which we know will trigger the \c |
| StateSwitchTransition to the selected state. |
| |
| \snippet animation/moveblocks/main.cpp 12 |
| |
| This is where the magic happens. We assign a number to each state |
| added. This number is given to both a StateSwitchTransition and to |
| StateSwitchEvents. As we have seen, state switch events will |
| trigger a transition with the same number. |
| |
| \section1 The StateSwitchTransition Class |
| |
| \c StateSwitchTransition inherits QAbstractTransition and triggers |
| on \c{StateSwitchEvent}s. It contains only inline functions, so |
| let's take a look at its \l{QAbstractTransition::}{eventTest()} |
| function, which is the only function that we define.. |
| |
| \snippet animation/moveblocks/main.cpp 14 |
| |
| \c eventTest is called by QStateMachine when it checks whether a |
| transition should be triggered--a return value of true means that |
| it will. We simply check if our assigned number is equal to the |
| event's number (in which case we fire away). |
| |
| \section1 The StateSwitchEvent Class |
| |
| \c StateSwitchEvent inherits QEvent, and holds a number that has |
| been assigned to a state and state switch transition by |
| \c StateSwitcher. We have already seen how it is used to trigger |
| \c{StateSwitchTransition}s in \c StateSwitcher. |
| |
| \snippet animation/moveblocks/main.cpp 15 |
| |
| We only have inlined functions in this class, so a look at its |
| definition will do. |
| |
| \section1 The QGraphicsRectWidget Class |
| |
| QGraphicsRectWidget inherits QGraphicsWidget and simply paints its |
| \l{QWidget::}{rect()} blue. We inline \l{QWidget::}{paintEvent()}, |
| which is the only function we define. Here is the |
| QGraphicsRectWidget class definition: |
| |
| \snippet animation/moveblocks/main.cpp 16 |
| |
| \section1 Moving On |
| |
| The technique shown in this example works equally well for all |
| \l{QPropertyAnimation}s. As long as the value to be animated is a |
| Qt property, you can insert an animation of it into a state graph. |
| |
| QState::addAnimation() takes a QAbstractAnimation, so any type |
| of animation can be inserted into the graph. |
| */ |
| |