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