diff options
Diffstat (limited to 'doc/src/examples/dragdroprobot.qdoc')
-rw-r--r-- | doc/src/examples/dragdroprobot.qdoc | 365 |
1 files changed, 0 insertions, 365 deletions
diff --git a/doc/src/examples/dragdroprobot.qdoc b/doc/src/examples/dragdroprobot.qdoc deleted file mode 100644 index c6563a5286..0000000000 --- a/doc/src/examples/dragdroprobot.qdoc +++ /dev/null @@ -1,365 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example graphicsview/dragdroprobot - \title Drag and Drop Robot Example - - The Drag and Drop Robot example shows how to implement Drag and Drop in a - QGraphicsItem subclass, as well as how to animate items using Qt's - \l{Animation Framework}. - - \image dragdroprobot-example.png - - Graphics View provides the QGraphicsScene class for managing and - interacting with a large number of custom-made 2D graphical items derived - from the QGraphicsItem class, and a QGraphicsView widget for visualizing - the items, with support for zooming and rotation. - - This example consists of a \c Robot class, a \c ColorItem class, and a main - function: the \c Robot class describes a simple robot consisting of several - \c RobotPart derived limbs, including \c RobotHead and \c RobotLimb, the \c - ColorItem class provides a draggable colored ellipse, and the \c main() - function provides the main application window. - - We will first review the \c Robot class to see how to assemble the - different parts so that they can be individually rotated and animated using - QPropertyAnimation, and we will then review the \c ColorItem class to - demonstrate how to implement Drag and Drop between items. Finally we will - review the main() function to see how we can put all the pieces together, - to form the final application. - - \section1 Robot Class Definition - - The robot consists of three main classes: the \c RobotHead, the \c - RobotTorso, and the \c RobotLimb, which is used for the upper and lower - arms and legs. All parts derive from the \c RobotPart class, which in turn - inherits \c QGraphicsObject. The \c Robot class itself has no visual - appearance and serves only as a root node for the robot. - - Let's start with the \c RobotPart class declaration. - - \snippet examples/graphicsview/dragdroprobot/robot.h 0 - - This base class inherits QGraphicsObject. QGraphicsObject provides signals - and slots through inheriting QObject, and it also declares QGraphicsItem's - properties using Q_PROPERTY, which makes the properties accessible for - QPropertyAnimation. - - RobotPart also implements the three most important event handlers for - accepting drop events: - \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()}, - \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()}, and - \l{QGraphicsItem::dropEvent()}{dropEvent()}. - - The color is stored as a member variable, along with the \c dragOver - variable, which we will use later to indicate visually that the limb can - accept colors that are is dragged onto it. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 0 - - \c RobotPart's constructor initializes the dragOver member and sets the - color to Qt::lightGray. In the constructor body we enable support for - accepting drop events by calling - \l{QGraphicsItem::setAcceptDrops()}{setAcceptDrops(true)}. - - The rest of this class's implementation is to support Drag and Drop. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 1 - - The \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} handler is called - when a Drag and Drop element is dragged into the robot part's area. - - The handler implementation determines whether or not this item as a whole - can accept the mime data assiciated with the incoming drag object. \c - RobotPart provides a base behavior for all parts that accepts color drops. - So if the incoming drag object contains a color, the event is accepted, we - set \c dragOver to \c true and call update() to help provide positive - visual feedback to the user; otherwise the event is ignored, which in turn - allows the event to propagate to parent elements. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 2 - - The \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()} handler is called - when a Drag and Drop element is dragged away from the robot part's area. - Our implementation simply resets \e dragOver to false and calls - \l{QGraphicsItem::update()}{update()} to help provide visual feedback that - the drag has left this item. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 3 - - The \l{QGraphicsItem::dropEvent()}{dropEvent()} handler is called when a - Drag and Drop element is dropped onto an item (i.e., when the mouse button - is released over the item while dragging). - - We reset \c dragOver to false, assign the item's new color, and call - \l{QGraphicsItem::update()}{update()}. - - The declaration and implementation of \c RobotHead, \c RobotTorso, and \c - RobotLimb are practically identical. We will review \c RobotHead in detail, - as this class has one minor difference, and leave the other classes as an - exercise for the reader. - - \snippet examples/graphicsview/dragdroprobot/robot.h 1 - - The \c RobotHead class inherits \c RobotPart and provides the necessary - implementations of \l{QGraphicsItem::boundingRect()}{boundingRect()} and - \l{QGraphicsItem::paint()}{paint()}. It also reimplements - \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} and dropEvent() to - provide special handling of image drops. - - The class contains a private pixmap member that we can use to implement - support for accepting image drops. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 4 - - \c RobotHead has a rather plain constructor that simply forwards to - \c RobotPart's constructor. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 5 - - The \l{QGraphicsItem::boundingRect()}{boundingRect()} reimplementation - returns the extents for the head. Because we want the center of rotation to - be the bottom center of the item, we have chosen a bounding rectangle that - starts at (-15, -50) and extends to 30 units wide and 50 units tall. When - rotating the head, the "neck" will stay still while the top of the head - tilts from side to side. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 6 - - In \l{QGraphicsItem::paint()}{paint()} we draw the actual head. The - implementation is split into two sections; if an image has been dropped - onto the head, we draw the image, otherwise we draw a round rectangular - robot head with simple vector graphics. - - For performance reasons, depending on the complexity of what is painted, it - can often be faster to draw the head as an image rather than using a - sequence of vector operations. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 7 - - The robot head can accept image drops. In order to support this, its - reimplementation of \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} - checks if the drag object contains image data, and if it does, then the - event is accepted. Otherwise we fall back to the base \c RobotPart - implementation. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 8 - - To follow up on image support, we must also implement - \l{QGraphicsItem::dropEvent()}{dropEvent()}. We check if the drag object - contains image data, and if it does, we store this data as a member pixmap - and call \l{QGraphicsItem::update()}{update()}. This pixmap is used inside - the \l{QGraphicsItem::paint()}{paint()} implementation that we reviewed - before. - - \c RobotTorso and \c RobotLimb are similar to \c RobotHead, so let's - skip directly to the \c Robot class. - - \snippet examples/graphicsview/dragdroprobot/robot.h 4 - - The \c Robot class also inherits \c RobotPart, and like the other parts it - also implements \l{QGraphicsItem::boundingRect()}{boundingRect()} and - \l{QGraphicsItem::paint()}{paint()}. It provides a rather special - implementation, though: - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 9 - - Because the \c Robot class is only used as a base node for the rest of the - robot, it has no visual representation. Its - \l{QGraphicsItem::boundingRect()}{boundingRect()} implementation can - therefore return a null QRectF, and its paint() function does nothing. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 10 - - The constructor starts by setting the flag - \l{QGraphicsItem::ItemHasNoContents}{ItemHasNoContents}, which is a minor - optimization for items that have no visual appearance. - - We then construct all the robot parts (head, torso, and upper/lower arms - and legs). The stacking order is very important, and we use the - parent-child hierarchy to ensure the elements rotate and move properly. We - construct the torso first, as this is the root element. We then construct - the head and pass the torso to \c HeadItem's constructor. This will make - the head a child of the torso; if you rotate the torso, the head will - follow. The same pattern is applied to the rest of the limbs. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 11 - - Each robot part is carefully positioned. For example, the upper left arm is - moved precisely to the top-left area of the torso, and the upper right arm - is moved to the top-right area. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 12 - - The next section creates all animation objects. This snippet shows the two - animations that operate on the head's scale and rotation. The two - QPropertyAnimation instances simply set the object, property, and - respective start and end values. - - All animations are controlled by one top-level parallel animation group. - The scale and rotation animations are added to this group. - - The rest of the animations are defined in a similar way. - - \snippet examples/graphicsview/dragdroprobot/robot.cpp 13 - - Finally we set an easing curve and duration on each animation, ensure the - toplevel animation group loops forever, and start the toplevel animation. - - \section1 ColorItem Class Definition - - The \c ColorItem class represents a circular item that can be pressed to - drag colors onto robot parts. - - \snippet examples/graphicsview/dragdroprobot/coloritem.h 0 - - This class is very simple. It does not use animations, and has no need for - properties nor signals and slots, so to save resources, it's most natural - that it inherits QGraphicsItem (as opposed to QGraphicsObject). - - It declares the mandatory \l{QGraphicsItem::boundingRect()}{boundingRect()} - and \l{QGraphicsItem::paint()}{paint()} functions, and adds - reimplementations of - \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()}, - \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()}, and - \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()}. It contains a - single private color member. - - Let's take a look at its implementation. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 0 - - \c ColorItem's constructor assigns an opaque random color to its color - member by making use of qrand(). For improved usability, it assigns a - tooltip that provides a useful hint to the user, and it also sets a - suitable cursor. This ensures that the cursor will chance to - Qt::OpenHandCursor when the mouse pointer hovers over the item. - - Finally, we call - \l{QGraphicsItem::setAcceptedMouseButtons()}{setAcceptedMouseButtons()} to - ensure that this item can only process Qt::LeftButton. This simplifies the - mouse event handlers greatly, as we can always assume that only the left - mouse button is pressed and released. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 1 - - The item's bounding rect is a fixed 30x30 units centered around the item's - origin (0, 0), and adjusted by 0.5 units in all directions to allow a - scalable pen to draw its outline. For a final visual touch the bounds - also compensate with a few units down and to the right to make room - for a simple dropshadow. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 2 - - The \l{QGraphicsItem::paint()}{paint()} implementation draws an ellipse - with a 1-unit black outline, a plain color fill, and a dark gray - dropshadow. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 3 - - The \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()} handler is - called when you press the mouse button inside the item's area. Our - implementation simply sets the cursor to Qt::ClosedHandCursor. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 4 - - The \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()} handler is - called when you release the mouse button after having pressed it inside an - item's area. Our implementation sets the cursor back to Qt::OpenHandCursor. - The mouse press and release event handlers together provide useful visual - feedback to the user: when you move the mouse pointer over a \c CircleItem, - the cursor changes to an open hand. Pressing the item will show a closed - hand cursor. Releasing will restore to an open hand cursor again. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 5 - - The \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()} handler is called - when you move the mouse around after pressing the mouse button inside the - \c ColorItem's area. This implementation provides the most important piece - of logic for \c CircleItem: the code that starts and manages drags. - - The implementation starts by checking if the mouse has been dragged far - enough to eliminate mouse jitter noise. We only want to start a drag if the - mouse has been dragged farther than the application start drag distance. - - Continuing, we create a QDrag object, passing the event - \l{QGraphicsSceneEvent::widget()}{widget} (i.e., the QGraphicsView - viewport) to its constructor. Qt will ensure that this object is deleted at - the right time. We also create a QMimeData instance that can contain our - color or image data, and assign this to the drag object. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 6 - - This snippet has a somewhat random outcome: once in a while, a special - image is assigned to the drag object's mime data. The pixmap is also - assiged as the drag object's pixmap. This will ensure that you can see the - image that is being dragged as a pixmap under the mouse cursor. - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 7 - - Otherwise, and this is the most common outcome, a simple color is assigned - to the drag object's mime data. We render this \c ColorItem into a new - pixmap to give the user visual feedback that the color is being "dragged". - - \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 8 - - Finally we execute the drag. QDrag::exec() will reenter the event loop, and - only exit if the drag has either been dropped, or canceled. In any case we - reset the cursor to Qt::OpenHandCursor. - - \section1 The main() Function - - Now that the \c Robot and \c ColorItem classes are complete, we can put all - the pieces together inside the main() function. - - \snippet examples/graphicsview/dragdroprobot/main.cpp 0 - - We start off by constructing QApplication, and initializing the random - number generator. This ensures that the color items have different colors - every time the application starts. - - \snippet examples/graphicsview/dragdroprobot/main.cpp 1 - - We construct a fixed size scene, and create 10 \c ColorItem instances - arranged in a circle. Each item is added to the scene. - - In the center of this circle we create one \c Robot instance. The - robot is scaled and moved up a few units. It is then added to the scene. - - \snippet examples/graphicsview/dragdroprobot/main.cpp 2 - - Finally we create a QGraphicsView window, and assign the scene to it. - - For increased visual quality, we enable antialiasing. We also choose to use - bounding rectangle updates to simplify visual update handling. - The view is given a fixed sand-colored background, and a window title. - - We then show the view. The animations start immediately after - control enters the event loop. -*/ - |