|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example animation/moveblocks |
|
44 \title Move Blocks Example |
|
45 |
|
46 The Move Blocks example shows how to animate items in a |
|
47 QGraphicsScene using a QStateMachine with a custom transition. |
|
48 |
|
49 \image moveblocks-example.png |
|
50 |
|
51 The example animates the blue blocks that you can see in the image |
|
52 above. The animation moves the blocks between four preset positions. |
|
53 |
|
54 The example consists of the following classes: |
|
55 |
|
56 \list |
|
57 \o \c StateSwitcher inherits QState and can add |
|
58 \c {StateSwitchTransition}s to other states. |
|
59 When entered, it will randomly transition to one of these |
|
60 states. |
|
61 \o \c StateSwitchTransition is a custom transition that |
|
62 triggers on \c{StateSwitchEvent}s. |
|
63 \o \c StateSwitchEvent is a QEvent that trigger \c{StateSwitchTransition}s. |
|
64 \o \c QGraphicsRectWidget is a QGraphicsWidget that simply |
|
65 paints its background in a solid \l{Qt::}{blue} color. |
|
66 \endlist |
|
67 |
|
68 The blocks are instances of \c QGraphicsRectWidget and are |
|
69 animated in a QGraphicsScene. We do this by building a state |
|
70 graph, which we insert animations into. The graph is then executed |
|
71 in a QStateMachine. All this is done in \c main(). |
|
72 Let's look at the \c main() function first. |
|
73 |
|
74 \section1 The \c main() Function |
|
75 |
|
76 After QApplication has been initialized, we set up the |
|
77 QGraphicsScene with its \c{QGraphicsRectWidget}s. |
|
78 |
|
79 \snippet examples/animation/moveblocks/main.cpp 1 |
|
80 |
|
81 After adding the scene to a QGraphicsView, it is time to build the |
|
82 state graph. Let's first look at a statechart of what we are |
|
83 trying to build. |
|
84 |
|
85 \image move-blocks-chart.png |
|
86 |
|
87 Note that the \c group has seven sub states, but we have only |
|
88 included three of them in the diagram. The code that builds this |
|
89 graph will be examined line-by-line, and will show how the graph |
|
90 works. First off, we construct the \c group state: |
|
91 |
|
92 \snippet examples/animation/moveblocks/main.cpp 2 |
|
93 |
|
94 The timer is used to add a delay between each time the blocks are |
|
95 moved. The timer is started when \c group is entered. As we will |
|
96 see later, \c group has a transition back to the \c StateSwitcher |
|
97 when the timer times out. \c group is the initial state in the |
|
98 machine, so an animation will be scheduled when the example is |
|
99 started. |
|
100 |
|
101 \snippet examples/animation/moveblocks/main.cpp 3 |
|
102 \dots |
|
103 \snippet examples/animation/moveblocks/main.cpp 4 |
|
104 |
|
105 \c createGeometryState() returns a QState that will set the |
|
106 geometry of our items upon entry. It also assigns \c group as the |
|
107 parent of this state. |
|
108 |
|
109 A QPropertyAnimation inserted into a transition will use the |
|
110 values assigned to a QState (with QState::assignProperty()), i.e., |
|
111 the animation will interpolate between the current values of the |
|
112 properties and the values in the target state. We add animated |
|
113 transitions to the state graph later. |
|
114 |
|
115 \snippet examples/animation/moveblocks/main.cpp 5 |
|
116 |
|
117 We move the items in parallel. Each item is added to \c |
|
118 animationGroup, which is the animation that is inserted into the |
|
119 transitions. |
|
120 |
|
121 \snippet examples/animation/moveblocks/main.cpp 6 |
|
122 |
|
123 The sequential animation group, \c subGroup, helps us insert a |
|
124 delay between the animation of each item. |
|
125 |
|
126 \snippet examples/animation/moveblocks/main.cpp 7 |
|
127 \dots |
|
128 \snippet examples/animation/moveblocks/main.cpp 8 |
|
129 |
|
130 A StateSwitchTransition is added to the state switcher |
|
131 in \c StateSwitcher::addState(). We also add the animation in this |
|
132 function. Since QPropertyAnimation uses the values from the |
|
133 states, we can insert the same QPropertyAnimation instance in all |
|
134 \c {StateSwitchTransition}s. |
|
135 |
|
136 As mentioned previously, we add a transition to the state switcher |
|
137 that triggers when the timer times out. |
|
138 |
|
139 \snippet examples/animation/moveblocks/main.cpp 9 |
|
140 |
|
141 Finally, we can create the state machine, add our initial state, |
|
142 and start execution of the state graph. |
|
143 |
|
144 \section2 The \c createGemetryState() Function |
|
145 |
|
146 In \c createGeometryState(), we set up the geometry for each |
|
147 graphics item. |
|
148 |
|
149 \snippet examples/animation/moveblocks/main.cpp 13 |
|
150 |
|
151 As mentioned before, QAbstractTransition will set up an animation |
|
152 added with \l{QAbstractTransition::}{addAnimation()} using |
|
153 property values set with \l{QState::}{assignProperty()}. |
|
154 |
|
155 \section1 The StateSwitcher Class |
|
156 |
|
157 \c StateSwitcher has state switch transitions to each \l{QState}s |
|
158 we created with \c createGemetryState(). Its job is to transition |
|
159 to one of these states at random when it is entered. |
|
160 |
|
161 All functions in \c StateSwitcher are inlined. We'll step through |
|
162 its definition. |
|
163 |
|
164 \snippet examples/animation/moveblocks/main.cpp 10 |
|
165 |
|
166 \c StateSwitcher is a state designed for a particular purpose and |
|
167 will always be a top-level state. We use \c m_stateCount to keep |
|
168 track of how many states we are managing, and \c m_lastIndex to |
|
169 remember which state was the last state to which we transitioned. |
|
170 |
|
171 \snippet examples/animation/moveblocks/main.cpp 11 |
|
172 |
|
173 We select the next state we are going to transition to, and post a |
|
174 \c StateSwitchEvent, which we know will trigger the \c |
|
175 StateSwitchTransition to the selected state. |
|
176 |
|
177 \snippet examples/animation/moveblocks/main.cpp 12 |
|
178 |
|
179 This is where the magic happens. We assign a number to each state |
|
180 added. This number is given to both a StateSwitchTransition and to |
|
181 StateSwitchEvents. As we have seen, state switch events will |
|
182 trigger a transition with the same number. |
|
183 |
|
184 \section1 The StateSwitchTransition Class |
|
185 |
|
186 \c StateSwitchTransition inherits QAbstractTransition and triggers |
|
187 on \c{StateSwitchEvent}s. It contains only inline functions, so |
|
188 let's take a look at its \l{QAbstractTransition::}{eventTest()} |
|
189 function, which is the only function that we define.. |
|
190 |
|
191 \snippet examples/animation/moveblocks/main.cpp 14 |
|
192 |
|
193 \c eventTest is called by QStateMachine when it checks whether a |
|
194 transition should be triggered--a return value of true means that |
|
195 it will. We simply check if our assigned number is equal to the |
|
196 event's number (in which case we fire away). |
|
197 |
|
198 \section1 The StateSwitchEvent Class |
|
199 |
|
200 \c StateSwitchEvent inherits QEvent, and holds a number that has |
|
201 been assigned to a state and state switch transition by |
|
202 \c StateSwitcher. We have already seen how it is used to trigger |
|
203 \c{StateSwitchTransition}s in \c StateSwitcher. |
|
204 |
|
205 \snippet examples/animation/moveblocks/main.cpp 15 |
|
206 |
|
207 We only have inlined functions in this class, so a look at its |
|
208 definition will do. |
|
209 |
|
210 \section1 The QGraphicsRectWidget Class |
|
211 |
|
212 QGraphicsRectWidget inherits QGraphicsWidget and simply paints its |
|
213 \l{QWidget::}{rect()} blue. We inline \l{QWidget::}{paintEvent()}, |
|
214 which is the only function we define. Here is the |
|
215 QGraphicsRectWidget class definition: |
|
216 |
|
217 \snippet examples/animation/moveblocks/main.cpp 16 |
|
218 |
|
219 \section1 Moving On |
|
220 |
|
221 The technique shown in this example works equally well for all |
|
222 \l{QPropertyAnimation}s. As long as the value to be animated is a |
|
223 Qt property, you can insert an animation of it into a state graph. |
|
224 |
|
225 QState::addAnimation() takes a QAbstractAnimation, so any type |
|
226 of animation can be inserted into the graph. |
|
227 */ |
|
228 |