Changeset 846 for trunk/doc/src/examples/dragdroprobot.qdoc
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/doc/src/examples/dragdroprobot.qdoc
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 7 7 ** This file is part of the documentation of the Qt Toolkit. 8 8 ** 9 ** $QT_BEGIN_LICENSE: LGPL$9 ** $QT_BEGIN_LICENSE:FDL$ 10 10 ** Commercial Usage 11 11 ** Licensees holding valid Qt Commercial licenses may use this file in 12 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. 13 ** Software or, alternatively, in accordance with the terms contained in a 14 ** written agreement between you and Nokia. 15 ** 16 ** GNU Free Documentation License 17 ** Alternatively, this file may be used under the terms of the GNU Free 18 ** Documentation License version 1.3 as published by the Free Software 19 ** Foundation and appearing in the file included in the packaging of this 20 ** file. 35 21 ** 36 22 ** If you have questions regarding the use of this file, please contact … … 44 30 \title Drag and Drop Robot Example 45 31 46 This GraphicsView example shows how to implement drag and drop in47 a QGraphicsItem subclass, as well as how to animate items using48 QGraphicsItemAnimation and QTimeLine.32 This GraphicsView example shows how to implement Drag and Drop in a 33 QGraphicsItem subclass, as well as how to animate items using Qt's 34 \l{Animation Framework}. 49 35 50 36 \image dragdroprobot-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 derived 40 from the QGraphicsItem class, and a QGraphicsView widget for visualizing 41 the items, with support for zooming and rotation. 42 43 This example consists of a \c Robot class, a \c ColorItem class, and a main 44 function: the \c Robot class describes a simple robot consisting of several 45 \c RobotPart derived limbs, including \c RobotHead and \c RobotLimb, the \c 46 ColorItem class provides a draggable colored ellipse, and the \c main() 47 function provides the main application window. 48 49 We will first review the \c Robot class to see how to assemble the 50 different parts so that they can be individually rotated and animated using 51 QPropertyAnimation, and we will then review the \c ColorItem class to 52 demonstrate how to implement Drag and Drop between items. Finally we will 53 review the main() function to see how we can put all the pieces together, 54 to form the final application. 55 56 \section1 Robot Class Definition 57 58 The robot consists of three main classes: the \c RobotHead, the \c 59 RobotTorso, and the \c RobotLimb, which is used for the upper and lower 60 arms and legs. All parts derive from the \c RobotPart class, which in turn 61 inherits \c QGraphicsObject. The \c Robot class itself has no visual 62 appearance and serves only as a root node for the robot. 63 64 Let's start with the \c RobotPart class declaration. 65 66 \snippet examples/graphicsview/dragdroprobot/robot.h 0 67 68 This base class inherits QGraphicsObject. QGraphicsObject provides signals 69 and slots through inheriting QObject, and it also declares QGraphicsItem's 70 properties using Q_PROPERTY, which makes the properties accessible for 71 QPropertyAnimation. 72 73 RobotPart also implements the three most important event handlers for 74 accepting drop events: 75 \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()}, 76 \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()}, and 77 \l{QGraphicsItem::dropEvent()}{dropEvent()}. 78 79 The color is stored as a member variable, along with the \c dragOver 80 variable, which we will use later to indicate visually that the limb can 81 accept colors that are is dragged onto it. 82 83 \snippet examples/graphicsview/dragdroprobot/robot.cpp 0 84 85 \c RobotPart's constructor initializes the dragOver member and sets the 86 color to Qt::lightGray. In the constructor body we enable support for 87 accepting drop events by calling 88 \l{QGraphicsItem::setAcceptDrops()}{setAcceptDrops(true)}. 89 90 The rest of this class's implementation is to support Drag and Drop. 91 92 \snippet examples/graphicsview/dragdroprobot/robot.cpp 1 93 94 The \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} handler is called 95 when a Drag and Drop element is dragged into the robot part's area. 96 97 The handler implementation determines whether or not this item as a whole 98 can accept the mime data assiciated with the incoming drag object. \c 99 RobotPart provides a base behavior for all parts that accepts color drops. 100 So if the incoming drag object contains a color, the event is accepted, we 101 set \c dragOver to \c true and call update() to help provide positive 102 visual feedback to the user; otherwise the event is ignored, which in turn 103 allows the event to propagate to parent elements. 104 105 \snippet examples/graphicsview/dragdroprobot/robot.cpp 2 106 107 The \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()} handler is called 108 when a Drag and Drop element is dragged away from the robot part's area. 109 Our implementation simply resets \e dragOver to false and calls 110 \l{QGraphicsItem::update()}{update()} to help provide visual feedback that 111 the drag has left this item. 112 113 \snippet examples/graphicsview/dragdroprobot/robot.cpp 3 114 115 The \l{QGraphicsItem::dropEvent()}{dropEvent()} handler is called when a 116 Drag and Drop element is dropped onto an item (i.e., when the mouse button 117 is released over the item while dragging). 118 119 We reset \c dragOver to false, assign the item's new color, and call 120 \l{QGraphicsItem::update()}{update()}. 121 122 The declaration and implementation of \c RobotHead, \c RobotTorso, and \c 123 RobotLimb are practically identical. We will review \c RobotHead in detail, 124 as this class has one minor difference, and leave the other classes as an 125 exercise for the reader. 126 127 \snippet examples/graphicsview/dragdroprobot/robot.h 1 128 129 The \c RobotHead class inherits \c RobotPart and provides the necessary 130 implementations of \l{QGraphicsItem::boundingRect()}{boundingRect()} and 131 \l{QGraphicsItem::paint()}{paint()}. It also reimplements 132 \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} and dropEvent() to 133 provide special handling of image drops. 134 135 The class contains a private pixmap member that we can use to implement 136 support for accepting image drops. 137 138 \snippet examples/graphicsview/dragdroprobot/robot.cpp 4 139 140 \c RobotHead has a rather plain constructor that simply forwards to 141 \c RobotPart's constructor. 142 143 \snippet examples/graphicsview/dragdroprobot/robot.cpp 5 144 145 The \l{QGraphicsItem::boundingRect()}{boundingRect()} reimplementation 146 returns the extents for the head. Because we want the center of rotation to 147 be the bottom center of the item, we have chosen a bounding rectangle that 148 starts at (-15, -50) and extends to 30 units wide and 50 units tall. When 149 rotating the head, the "neck" will stay still while the top of the head 150 tilts from side to side. 151 152 \snippet examples/graphicsview/dragdroprobot/robot.cpp 6 153 154 In \l{QGraphicsItem::paint()}{paint()} we draw the actual head. The 155 implementation is split into two sections; if an image has been dropped 156 onto the head, we draw the image, otherwise we draw a round rectangular 157 robot head with simple vector graphics. 158 159 For performance reasons, depending on the complexity of what is painted, it 160 can often be faster to draw the head as an image rather than using a 161 sequence of vector operations. 162 163 \snippet examples/graphicsview/dragdroprobot/robot.cpp 7 164 165 The robot head can accept image drops. In order to support this, its 166 reimplementation of \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} 167 checks if the drag object contains image data, and if it does, then the 168 event is accepted. Otherwise we fall back to the base \c RobotPart 169 implementation. 170 171 \snippet examples/graphicsview/dragdroprobot/robot.cpp 8 172 173 To follow up on image support, we must also implement 174 \l{QGraphicsItem::dropEvent()}{dropEvent()}. We check if the drag object 175 contains image data, and if it does, we store this data as a member pixmap 176 and call \l{QGraphicsItem::update()}{update()}. This pixmap is used inside 177 the \l{QGraphicsItem::paint()}{paint()} implementation that we reviewed 178 before. 179 180 \c RobotTorso and \c RobotLimb are similar to \c RobotHead, so let's 181 skip directly to the \c Robot class. 182 183 \snippet examples/graphicsview/dragdroprobot/robot.h 4 184 185 The \c Robot class also inherits \c RobotPart, and like the other parts it 186 also implements \l{QGraphicsItem::boundingRect()}{boundingRect()} and 187 \l{QGraphicsItem::paint()}{paint()}. It provides a rather special 188 implementation, though: 189 190 \snippet examples/graphicsview/dragdroprobot/robot.cpp 9 191 192 Because the \c Robot class is only used as a base node for the rest of the 193 robot, it has no visual representation. Its 194 \l{QGraphicsItem::boundingRect()}{boundingRect()} implementation can 195 therefore return a null QRectF, and its paint() function does nothing. 196 197 \snippet examples/graphicsview/dragdroprobot/robot.cpp 10 198 199 The constuctor starts by setting the flag 200 \l{QGraphicsItem::ItemHasNoContents}{ItemHasNoContents}, which is a minor 201 optimization for items that have no visual appearance. 202 203 We then construct all the robot parts (head, torso, and upper/lower arms 204 and legs). The stacking order is very important, and we use the 205 parent-child hierarchy to ensure the elements rotate and move properly. We 206 construct the torso first, as this is the root element. We then construct 207 the head and pass the torso to \c HeadItem's constructor. This will make 208 the head a child of the torso; if you rotate the torso, the head will 209 follow. The same pattern is applied to the rest of the limbs. 210 211 \snippet examples/graphicsview/dragdroprobot/robot.cpp 11 212 213 Each robot part is carefully positioned. For example, the upper left arm is 214 moved precisely to the top-left area of the torso, and the upper right arm 215 is moved to the top-right area. 216 217 \snippet examples/graphicsview/dragdroprobot/robot.cpp 12 218 219 The next section creates all animation objects. This snippet shows the two 220 animations that operate on the head's scale and rotation. The two 221 QPropertyAnimation instances simply set the object, property, and 222 respective start and end values. 223 224 All animations are controlled by one top-level parallel animation group. 225 The scale and rotation animations are added to this group. 226 227 The rest of the animations are defined in a similar way. 228 229 \snippet examples/graphicsview/dragdroprobot/robot.cpp 13 230 231 Finally we set an easing curve and duration on each animation, ensure the 232 toplevel animation group loops forever, and start the toplevel animation. 233 234 \section1 ColorItem Class Definition 235 236 The \c ColorItem class represents a circular item that can be pressed to 237 drag colors onto robot parts. 238 239 \snippet examples/graphicsview/dragdroprobot/coloritem.h 0 240 241 This class is very simple. It does not use animations, and has no need for 242 properties nor signals and slots, so to save resources, it's most natural 243 that it inherits QGraphicsItem (as opposed to QGraphicsObject). 244 245 It declares the mandatory \l{QGraphicsItem::boundingRect()}{boundingRect()} 246 and \l{QGraphicsItem::paint()}{paint()} functions, and adds 247 reimplementations of 248 \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()}, 249 \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()}, and 250 \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()}. It contains a 251 single private color member. 252 253 Let's take a look at its implementation. 254 255 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 0 256 257 \c ColorItem's constructor assigns an opaque random color to its color 258 member by making use of qrand(). For improved usability, it assigns a 259 tooltip that provides a useful hint to the user, and it also sets a 260 suitable cursor. This ensures that the cursor will chance to 261 Qt::OpenHandCursor when the mouse pointer hovers over the item. 262 263 Finally, we call 264 \l{QGraphicsItem::setAcceptedMouseButtons()}{setAcceptedMouseButtons()} to 265 ensure that this item can only process Qt::LeftButton. This simplifies the 266 mouse event handlers greatly, as we can always assume that only the left 267 mouse button is pressed and released. 268 269 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 1 270 271 The item's bounding rect is a fixed 30x30 units centered around the item's 272 origin (0, 0), and adjusted by 0.5 units in all directions to allow a 273 scalable pen to draw its outline. For a final visual touch the bounds 274 also compensate with a few units down and to the right to make room 275 for a simple dropshadow. 276 277 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 2 278 279 The \l{QGraphicsItem::paint()}{paint()} implementation draws an ellipse 280 with a 1-unit black outline, a plain color fill, and a dark gray 281 dropshadow. 282 283 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 3 284 285 The \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()} handler is 286 called when you press the mouse button inside the item's area. Our 287 implementation simply sets the cursor to Qt::ClosedHandCursor. 288 289 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 4 290 291 The \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()} handler is 292 called when you release the mouse button after having pressed it inside an 293 item's area. Our implementation sets the cursor back to Qt::OpenHandCursor. 294 The mouse press and release event handlers together provide useful visual 295 feedback to the user: when you move the mouse pointer over a \c CircleItem, 296 the cursor changes to an open hand. Pressing the item will show a closed 297 hand cursor. Releasing will restore to an open hand cursor again. 298 299 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 5 300 301 The \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()} handler is called 302 when you move the mouse around after pressing the mouse button inside the 303 \c ColorItem's area. This implementation provides the most important piece 304 of logic for \c CircleItem: the code that starts and manages drags. 305 306 The implementation starts by checking if the mouse has been dragged far 307 enough to eliminate mouse jitter noise. We only want to start a drag if the 308 mouse has been dragged farther than the application start drag distance. 309 310 Continuing, we create a QDrag object, passing the event 311 \l{QGraphicsSceneEvent::widget()}{widget} (i.e., the QGraphicsView 312 viewport) to its constructor. Qt will ensure that this object is deleted at 313 the right time. We also create a QMimeData instance that can contain our 314 color or image data, and assign this to the drag object. 315 316 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 6 317 318 This snippet has a somewhat random outcome: once in a while, a special 319 image is assigned to the drag object's mime data. The pixmap is also 320 assiged as the drag object's pixmap. This will ensure that you can see the 321 image that is being dragged as a pixmap under the mouse cursor. 322 323 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 7 324 325 Otherwise, and this is the most common outcome, a simple color is assigned 326 to the drag object's mime data. We render this \c ColorItem into a new 327 pixmap to give the user visual feedback that the color is being "dragged". 328 329 \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 8 330 331 Finally we execute the drag. QDrag::exec() will reenter the event loop, and 332 only exit if the drag has either been dropped, or canceled. In any case we 333 reset the cursor to Qt::OpenHandCursor. 334 335 \section1 The main() Function 336 337 Now that the \c Robot and \c ColorItem classes are complete, we can put all 338 the pieces together inside the main() function. 339 340 \snippet examples/graphicsview/dragdroprobot/main.cpp 0 341 342 We start off by constructing QApplication, and initializing the random 343 number generator. This ensures that the color items have different colors 344 every time the application starts. 345 346 \snippet examples/graphicsview/dragdroprobot/main.cpp 1 347 348 We construct a fixed size scene, and create 10 \c ColorItem instances 349 arranged in a circle. Each item is added to the scene. 350 351 In the center of this circle we create one \c Robot instance. The 352 robot is scaled and moved up a few units. It is then added to the scene. 353 354 \snippet examples/graphicsview/dragdroprobot/main.cpp 2 355 356 Finally we create a QGraphicsView window, and assign the scene to it. 357 358 For increased visual quality, we enable antialiasing. We also choose to use 359 bounding rectangle updates to simplify visual update handling. 360 The view is given a fixed sand-colored background, and a window title. 361 362 We then show the view. The animations start immediately after 363 control enters the event loop. 51 364 */ 365
Note:
See TracChangeset
for help on using the changeset viewer.