source: trunk/doc/src/examples/collidingmice-example.qdoc@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 13.1 KB
Line 
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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \example graphicsview/collidingmice
44 \title Colliding Mice Example
45
46 The Colliding Mice example shows how to use the Graphics View
47 framework to implement animated items and detect collision between
48 items.
49
50 \image collidingmice-example.png
51
52 Graphics View provides the QGraphicsScene class for managing and
53 interacting with a large number of custom-made 2D graphical items
54 derived from the QGraphicsItem class, and a QGraphicsView widget
55 for visualizing the items, with support for zooming and rotation.
56
57 The example consists of an item class and a main function:
58 the \c Mouse class represents the individual mice extending
59 QGraphicsItem, and the \c main() function provides the main
60 application window.
61
62 We will first review the \c Mouse class to see how to animate
63 items and detect item collision, and then we will review the \c
64 main() function to see how to put the items into a scene and how to
65 implement the corresponding view.
66
67 \section1 Mouse Class Definition
68
69 The \c mouse class inherits from QGraphicsItem. The
70 QGraphicsItem class is the base class for all graphical items in
71 the Graphics View framework, and provides a light-weight
72 foundation for writing your own custom items.
73
74 \snippet examples/graphicsview/collidingmice/mouse.h 0
75
76 When writing a custom graphics item, you must implement
77 QGraphicsItem's two pure virtual public functions: \l
78 {QGraphicsItem::}{boundingRect()}, which returns an estimate of
79 the area painted by the item, and \l {QGraphicsItem::}{paint()},
80 which implements the actual painting. In addition, we reimplement
81 the \l {QGraphicsItem::}{shape()} and \l {QGraphicsItem::}{advance()}.
82 We reimplement \l {QGraphicsItem::}{shape()} to return an accurate
83 shape of our mouse item; the default implementation simply returns
84 the item's bounding rectangle. We reimplement \l {QGraphicsItem::}{advance()}
85 to handle the animation so it all happens on one update.
86
87 \section1 Mouse Class Definition
88
89 When constructing a mouse item, we first ensure that all the item's
90 private variables are properly initialized:
91
92 \snippet examples/graphicsview/collidingmice/mouse.cpp 0
93
94 To calculate the various components of the mouse's color, we use
95 the global qrand() function which is a thread-safe version of the
96 standard C++ rand() function.
97
98 Then we call the \l {QGraphicsItem::setRotation()}{setRotation()} function
99 inherited from QGraphicsItem. Items live in their own local
100 coordinate system. Their coordinates are usually centered around
101 (0, 0), and this is also the center for all transformations. By
102 calling the item's \l {QGraphicsItem::setRotation()}{setRotation()} function
103 we alter the direction in which the mouse will start moving.
104
105 When the QGraphicsScene decides to advance the scene a frame it will call
106 QGraphicsItem::advance() on each of the items. This enables us to animate
107 our mouse using our reimplementation of the advance() function.
108
109 \snippet examples/graphicsview/collidingmice/mouse.cpp 4
110 \snippet examples/graphicsview/collidingmice/mouse.cpp 5
111 \snippet examples/graphicsview/collidingmice/mouse.cpp 6
112
113 First, we don't bother doing any advance if the step is 0 since we want to our advance in
114 the actual advance (advance() is called twice, once with step == 0 indicating that items
115 are about to advance and with step == 1 for the actual advance). We also ensure that the
116 mice stays within a circle with a radius of 150 pixels.
117
118 Note the \l {QGraphicsItem::mapFromScene()}{mapFromScene()}
119 function provided by QGraphicsItem. This function maps a position
120 given in \e scene coordinates, to the item's coordinate system.
121
122 \snippet examples/graphicsview/collidingmice/mouse.cpp 7
123 \snippet examples/graphicsview/collidingmice/mouse.cpp 8
124 \snippet examples/graphicsview/collidingmice/mouse.cpp 9
125 \codeline
126 \snippet examples/graphicsview/collidingmice/mouse.cpp 10
127
128 Then we try to avoid colliding with other mice.
129
130 \snippet examples/graphicsview/collidingmice/mouse.cpp 11
131
132 Finally, we calculate the mouse's speed and its eye direction (for
133 use when painting the mouse), and set its new position.
134
135 The position of an item describes its origin (local coordinate (0,
136 0)) in the parent coordinates. The \l {QGraphicsItem::setPos()}
137 function sets the position of the item to the given position in
138 the parent's coordinate system. For items with no parent, the
139 given position is interpreted as scene coordinates. QGraphicsItem
140 also provides a \l {QGraphicsItem::}{mapToParent()} function to
141 map a position given in item coordinates, to the parent's
142 coordinate system. If the item has no parent, the position will be
143 mapped to the scene's coordinate system instead.
144
145 Then it is time to provide an implementation for the pure virtual
146 functions inherited from QGraphicsItem. Let's first take a look at
147 the \l {QGraphicsItem::}{boundingRect()} function:
148
149 \snippet examples/graphicsview/collidingmice/mouse.cpp 1
150
151 The \l {QGraphicsItem::boundingRect()}{boundingRect()} function
152 defines the outer bounds of the item as a rectangle. Note that the
153 Graphics View framework uses the bounding rectangle to determine
154 whether the item requires redrawing, so all painting must be
155 restricted inside this rectangle.
156
157 \snippet examples/graphicsview/collidingmice/mouse.cpp 3
158
159 The Graphics View framework calls the \l
160 {QGraphicsItem::paint()}{paint()} function to paint the contents
161 of the item; the function paints the item in local coordinates.
162
163 Note the painting of the ears: Whenever a mouse item collides with
164 other mice items its ears are filled with red; otherwise they are
165 filled with dark yellow. We use the
166 QGraphicsScene::collidingItems() function to check if there are
167 any colliding mice. The actual collision detection is handled by
168 the Graphics View framework using shape-shape intersection. All we
169 have to do is to ensure that the QGraphicsItem::shape() function
170 returns an accurate shape for our item:
171
172 \snippet examples/graphicsview/collidingmice/mouse.cpp 2
173
174 Because the complexity of arbitrary shape-shape intersection grows
175 with an order of magnitude when the shapes are complex, this
176 operation can be noticably time consuming. An alternative approach
177 is to reimplement the \l
178 {QGraphicsItem::collidesWithItem()}{collidesWithItem()} function
179 to provide your own custom item and shape collision algorithm.
180
181 This completes the \c Mouse class implementation, it is now ready
182 for use. Let's take a look at the \c main() function to see how to
183 implement a scene for the mice and a view for displaying the
184 contents of the scene.
185
186 \section1 The Main() Function
187
188 In this example we have chosen to let the \c main() function
189 provide the main application window, creating the items and the
190 scene, putting the items into the scene and creating a
191 corresponding view.
192
193 \snippet examples/graphicsview/collidingmice/main.cpp 0
194
195 First, we create an application object and call the global
196 qsrand() function to specify the seed used to generate a new
197 random number sequence of pseudo random integers with the
198 previously mentioned qrand() function.
199
200 Then it is time to create the scene:
201
202 \snippet examples/graphicsview/collidingmice/main.cpp 1
203
204 The QGraphicsScene class serves as a container for
205 QGraphicsItems. It also provides functionality that lets you
206 efficiently determine the location of items as well as determining
207 which items that are visible within an arbitrary area on the
208 scene.
209
210 When creating a scene it is recommended to set the scene's
211 rectangle, i.e., the rectangle that defines the extent of the
212 scene. It is primarily used by QGraphicsView to determine the
213 view's default scrollable area, and by QGraphicsScene to manage
214 item indexing. If not explicitly set, the scene's default
215 rectangle will be the largest bounding rectangle of all the items
216 on the scene since the scene was created (i.e., the rectangle will
217 grow when items are added or moved in the scene, but it will never
218 shrink).
219
220 \snippet examples/graphicsview/collidingmice/main.cpp 2
221
222 The item index function is used to speed up item discovery. \l
223 {QGraphicsScene::NoIndex}{NoIndex} implies that item location is
224 of linear complexity, as all items on the scene are
225 searched. Adding, moving and removing items, however, is done in
226 constant time. This approach is ideal for dynamic scenes, where
227 many items are added, moved or removed continuously. The
228 alternative is \l {QGraphicsScene::BspTreeIndex}{BspTreeIndex}
229 which makes use of binary search resulting in item location
230 algorithms that are of an order closer to logarithmic complexity.
231
232 \snippet examples/graphicsview/collidingmice/main.cpp 3
233
234 Then we add the mice to the scene.
235
236 \snippet examples/graphicsview/collidingmice/main.cpp 4
237
238 To be able to view the scene we must also create a QGraphicsView
239 widget. The QGraphicsView class visualizes the contents of a scene
240 in a scrollable viewport. We also ensure that the contents is
241 rendered using antialiasing, and we create the cheese background
242 by setting the view's background brush.
243
244 The image used for the background is stored as a binary file in
245 the application's executable using Qt's \l {The Qt Resource
246 System}{resource system}. The QPixmap constructor accepts both
247 file names that refer to actual files on disk and file names that
248 refer to the application's embedded resources.
249
250 \snippet examples/graphicsview/collidingmice/main.cpp 5
251
252 Then we set the cache mode; QGraphicsView can cache pre-rendered
253 content in a pixmap, which is then drawn onto the viewport. The
254 purpose of such caching is to speed up the total rendering time
255 for areas that are slow to render, e.g., texture, gradient and
256 alpha blended backgrounds. The \l
257 {QGraphicsView::CacheMode}{CacheMode} property holds which parts
258 of the view that are cached, and the \l
259 {QGraphicsView::CacheBackground}{CacheBackground} flag enables
260 caching of the view's background.
261
262 By setting the \l {QGraphicsView::dragMode}{dragMode} property we
263 define what should happen when the user clicks on the scene
264 background and drags the mouse. The \l
265 {QGraphicsView::ScrollHandDrag}{ScrollHandDrag} flag makes the
266 cursor change into a pointing hand, and dragging the mouse around
267 will scroll the scrollbars.
268
269 \snippet examples/graphicsview/collidingmice/main.cpp 6
270
271 In the end, we set the application window's title and size before
272 we enter the main event loop using the QApplication::exec()
273 function.
274
275 Finally, we create a QTimer and connect its timeout() signal to the advance()
276 slot of the scene. Every time the timer fires, the scene will advance one frame.
277 We then tell the timer to fire every 1000/33 millisecond. This will
278 give us a frame rate of 30 frames a second, which is fast enough for most animations.
279 Doing the animation with a single timer connect to advance the scene ensures that all the
280 mice are moved at one point and, more importantly, only one update is sent to the screen
281 after all the mice have moved.
282*/
Note: See TracBrowser for help on using the repository browser.