doc/src/examples/collidingmice-example.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 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 */