path: root/examples
diff options
authorPaul Olav Tvete <>2012-11-30 11:08:33 +0100
committerThe Qt Project <>2012-11-30 18:37:35 +0100
commitd25bd0c37e7aa88df041e663e3f52ac54a9b38f1 (patch)
treebcbc329493419ac75a7dbd724a4052f108491161 /examples
parent0e7ba5e763807730d6138d490f1741ede137d0eb (diff)
Fix docs for Drag and Drop examples
Change-Id: Ic1622b64603f7634b697bd7d8412dcc9f1a8c3fa Reviewed-by: Gunnar Sletta <> Reviewed-by: Eskil Abrahamsen Blomfeldt <>
Diffstat (limited to 'examples')
-rw-r--r--examples/widgets/doc/images/draganddroppuzzle-example.pngbin0 -> 191122 bytes
-rw-r--r--examples/widgets/doc/images/fridgemagnets-example.pngbin0 -> 33012 bytes
3 files changed, 360 insertions, 0 deletions
diff --git a/examples/widgets/doc/images/draganddroppuzzle-example.png b/examples/widgets/doc/images/draganddroppuzzle-example.png
new file mode 100644
index 0000000000..812278210d
--- /dev/null
+++ b/examples/widgets/doc/images/draganddroppuzzle-example.png
Binary files differ
diff --git a/examples/widgets/doc/images/fridgemagnets-example.png b/examples/widgets/doc/images/fridgemagnets-example.png
new file mode 100644
index 0000000000..9adb572afc
--- /dev/null
+++ b/examples/widgets/doc/images/fridgemagnets-example.png
Binary files differ
diff --git a/examples/widgets/doc/src/fridgemagnets.qdoc b/examples/widgets/doc/src/fridgemagnets.qdoc
new file mode 100644
index 0000000000..b53c94f0bd
--- /dev/null
+++ b/examples/widgets/doc/src/fridgemagnets.qdoc
@@ -0,0 +1,360 @@
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact:
+** This file is part of the documentation of the Qt Toolkit.
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see For further information
+** use the contact form at
+** GNU Free Documentation License Usage
+** 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. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met:
+ \example draganddrop/fridgemagnets
+ \title Fridge Magnets Example
+ The Fridge Magnets example shows how to supply more than one type
+ of MIME-encoded data with a drag and drop operation.
+ \image fridgemagnets-example.png
+ With this application the user can play around with a collection
+ of fridge magnets, using drag and drop to form new sentences from
+ the words on the magnets. The example consists of two classes:
+ \list
+ \li \c DragLabel is a custom widget representing one
+ single fridge magnet.
+ \li \c DragWidget provides the main application window.
+ \endlist
+ We will first take a look at the \c DragLabel class, then we will
+ examine the \c DragWidget class.
+ \section1 DragLabel Class Definition
+ Each fridge magnet is represented by an instance of the \c
+ DragLabel class:
+ \snippet draganddrop/fridgemagnets/draglabel.h 0
+ Each instance of this QLabel subclass will be used to display an
+ pixmap generated from a text string. Since we cannot store both
+ text and a pixmap in a standard label, we declare a private variable
+ to hold the original text, and we define an additional member
+ function to allow it to be accessed.
+ \section1 DragLabel Class Implementation
+ In the \c DragLabel constructor, we first create a QImage object
+ on which we will draw the fridge magnet's text and frame:
+ \snippet draganddrop/fridgemagnets/draglabel.cpp 0
+ Its size depends on the current font size, and its format is
+ QImage::Format_ARGB32_Premultiplied; i.e., the image is stored
+ using a premultiplied 32-bit ARGB format (0xAARRGGBB).
+ We then construct a font object that uses the application's
+ default font, and set its style strategy. The style strategy tells
+ the font matching algorithm what type of fonts should be used to
+ find an appropriate default family. The QFont::ForceOutline forces
+ the use of outline fonts.
+ To draw the text and frame onto the image, we use the QPainter
+ class. QPainter provides highly optimized methods to do most of
+ the drawing GUI programs require. It can draw everything from
+ simple lines to complex shapes like pies and chords. It can also
+ draw aligned text and pixmaps.
+ \snippet draganddrop/fridgemagnets/draglabel.cpp 1
+ A painter can be activated by passing a paint device to the
+ constructor, or by using the \l{QPainter::}{begin()} method as we
+ do in this example. The \l{QPainter::}{end()} method deactivates
+ it. Note that the latter function is called automatically upon
+ destruction when the painter is actived by its constructor. The
+ QPainter::Antialiasing render hint ensures that the paint engine
+ will antialias the edges of primitives if possible.
+ When the painting is done, we convert our image to a pixmap using
+ QPixmap's \l {QPixmap::}{fromImage()} method. This method also
+ takes an optional flags argument, and converts the given image to
+ a pixmap using the specified flags to control the conversion (the
+ flags argument is a bitwise-OR of the Qt::ImageConversionFlags;
+ passing 0 for flags sets all the default options).
+ \snippet draganddrop/fridgemagnets/draglabel.cpp 2
+ Finally, we set the label's \l{QLabel::pixmap}{pixmap property}
+ and store the label's text for later use.
+ \e{Note that setting the pixmap clears any previous content, including
+ any text previously set using QLabel::setText(), and disables
+ the label widget's buddy shortcut, if any.}
+ \section1 DragWidget Class Definition
+ The \c DragWidget class inherits QWidget, providing support for
+ drag and drop operations:
+ \snippet draganddrop/fridgemagnets/dragwidget.h 0
+ To make the widget responsive to drag and drop operations, we simply
+ reimplement the \l{QWidget::}{dragEnterEvent()},
+ \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
+ handlers inherited from QWidget.
+ We also reimplement \l{QWidget::}{mousePressEvent()} to make the
+ widget responsive to mouse clicks. This is where we will write code
+ to start drag and drop operations.
+ \section1 DragWidget Class Implementation
+ In the constructor, we first open the file containing the words on
+ our fridge magnets:
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 0
+ QFile is an I/O device for reading and writing text and binary
+ files and resources, and may be used by itself or in combination
+ with QTextStream or QDataStream. We have chosen to read the
+ contents of the file using the QTextStream class that provides a
+ convenient interface for reading and writing text.
+ We then create the fridge magnets. As long as there is data (the
+ QTextStream::atEnd() method returns true if there is no more data
+ to be read from the stream), we read one line at a time using
+ QTextStream's \l {QTextStream::}{readLine()} method.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 1
+ For each line, we create a \c DragLabel object using the read line
+ as text, we calculate its position and ensure that it is visible by
+ calling the QWidget::show() method. We set the Qt::WA_DeleteOnClose
+ attribute on each label to ensure that any unused labels will be
+ deleted; we will need to create new labels and delete old ones when
+ they are dragged around, and this ensures that the example does not
+ leak memory.
+ We also set the \c FridgeMagnets widget's palette, minimum size
+ and window title.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 2
+ Finally, to enable our user to move the fridge magnets around, we
+ must also set the \c FridgeMagnets widget's
+ \l{QWidget::acceptDrops}{acceptDrops} property.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 3
+ Setting this property to true announces to the system that this
+ widget \e may be able to accept drop events (events that are sent
+ when drag and drop actions are completed). Later, we will
+ implement the functions that ensure that the widget accepts the
+ drop events it is interested in.
+ \section2 Dragging
+ Let's take a look at the \l{QWidget::}{mousePressEvent()} event
+ handler, where drag and drop operations begin:
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 13
+ \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 14
+ Mouse events occur when a mouse button is pressed or released
+ inside a widget, or when the mouse cursor is moved. By
+ reimplementing the \l{QWidget::}{mousePressEvent()} method we
+ ensure that we will receive mouse press events for the widget
+ containing the fridge magnets.
+ Whenever we receive such an event, we first check to see if the
+ position of the click coincides with one of the labels. If not,
+ we simply return.
+ If the user clicked a label, we determine the position of the
+ \e{hot spot} (the position of the click relative to the top-left
+ corner of the label). We create a byte array to store the label's
+ text and the hot spot, and we use a QDataStream object to stream
+ the data into the byte array.
+ With all the information in place, we create a new QMimeData object.
+ As mentioned above, QMimeData objects associate the data that they
+ hold with the corresponding MIME types to ensure that information
+ can be safely transferred between applications. The
+ \l{QMimeData::}{setData()} method sets the data associated with a
+ given MIME type. In our case, we associate our item data with the
+ custom \c application/x-fridgemagnet type.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 15
+ Note that we also associate the magnet's text with the
+ \c text/plain MIME type using QMimeData's \l{QMimeData::}{setText()}
+ method. Below, we will see how our widget detects both these MIME
+ types with its event handlers.
+ Finally, we create a QDrag object. It is the QDrag class that
+ handles most of the details of a drag and drop operation,
+ providing support for MIME-based drag and drop data transfer. The
+ data to be transferred by the drag and drop operation is contained
+ in a QMimeData object. When we call QDrag's
+ \l{QDrag::}{setMimeData()} method the ownership of our item data is
+ transferred to the QDrag object.
+ We call the \l{QDrag::}{setPixmap()} function to set the pixmap used
+ to represent the data during the drag and drop operation.
+ Typically, this pixmap shows an icon that represents the MIME type
+ of the data being transferred, but any pixmap can be used. In this
+ example, we simply use the pixmap used by the label itself to make
+ it look like the fridge magnet itself is being moved.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 16
+ We also specify the cursor's hot spot, its position relative to the
+ top-level corner of the drag pixmap, to be the point we calculated
+ above. This makes the process of dragging the label feel more natural
+ because the cursor always points to the same place on the label
+ during the drag operation.
+ We start the drag operation using QDrag's \l{QDrag::}{exec()} function,
+ requesting that the magnet is copied when the drag is completed.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 17
+ The function returns the drop action actually performed by the user
+ (this can be either a copy or a move action in this case); if this
+ action is equal to Qt::MoveAction we will close the activated
+ fridge magnet widget because we will create a new one to replace it
+ (see the \l{drop}{dropEvent()} implementation). Otherwise, if
+ the drop is outside our main widget, we simply show the widget in
+ its original position.
+ \section2 Dropping
+ When a a drag and drop action enters our widget, we will receive a
+ drag enter \e event. QDragEnterEvent inherits most of its
+ functionality from QDragMoveEvent, which in turn inherits most of
+ its functionality from QDropEvent. Note that we must accept this
+ event in order to receive the drag move events that are sent while
+ the drag and drop action is in progress. The drag enter event is
+ always immediately followed by a drag move event.
+ In our \c dragEnterEvent() implementation, we first determine
+ whether we support the event's MIME type or not:
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 4
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 5
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 6
+ If the type is \c application/x-fridgemagnet and the event
+ origins from any of this application's fridge magnet widgets, we
+ first set the event's drop action using the
+ QDropEvent::setDropAction() method. An event's drop action is the
+ action to be performed on the data by the target. Qt::MoveAction
+ indicates that the data is moved from the source to the target.
+ Then we call the event's \l {QDragMoveEvent::}{accept()} method to
+ indicate that we have handled the event. In general, unaccepted
+ events might be propagated to the parent widget. If the event
+ origins from any other widget, we simply accept the proposed
+ action.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 7
+ We also accept the proposed action if the event's MIME type is \c
+ text/plain, i.e., if QMimeData::hasText() returns true. If the
+ event has any other type, on the other hand, we call the event's
+ \l {QDragMoveEvent::}{ignore()} method allowing the event to be
+ propagated further.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 8
+ Drag move events occur when the cursor enters a widget, when it
+ moves within the widget, and when a modifier key is pressed on the
+ keyboard while the widget has focus. Our widget will receive drag
+ move events repeatedly while a drag is within its boundaries. We
+ reimplement the \l {QWidget::}{dragMoveEvent()} method, and
+ examine the event in the exact same way as we did with drag enter
+ events.
+ Note that the \l{QWidget::}{dropEvent()} event handler behaves
+ slightly differently: We first get hold of the event's MIME
+ data.
+ \target drop
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 9
+ The QMimeData class provides a container for data that
+ records information about its MIME type. QMimeData objects
+ associate the data that they hold with the corresponding MIME
+ types to ensure that information can be safely transferred between
+ applications, and copied around within the same application.
+ We retrieve the data associated with the \c application/x-fridgemagnet
+ MIME type using a data stream in order to create a new \c DragLabel
+ object.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 10
+ The QDataStream class provides serialization of binary data to a
+ QIODevice (a data stream is a binary stream of encoded information
+ which is completely independent of the host computer's operating
+ system, CPU or byte order).
+ Finally, we create a label and move it to the event's position:
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 11
+ If the source of the event is also the widget receiving the
+ drop event, we set the event's drop action to Qt::MoveAction and
+ call the event's \l{QDragMoveEvent::}{accept()}
+ method. Otherwise, we simply accept the proposed action. This
+ means that labels are moved rather than copied in the same
+ window. However, if we drag a label to a second instance of the
+ Fridge Magnets example, the default action is to copy it, leaving
+ the original in the first instance.
+ If the event's MIME type is \c text/plain (i.e., if
+ QMimeData::hasText() returns true) we retrieve its text and split
+ it into words. For each word we create a new \c DragLabel action,
+ and show it at the event's position plus an offset depending on
+ the number of words in the text. In the end we accept the proposed
+ action. This lets the user drop selected text from a text editor or
+ Web browser onto the widget to add more fridge magnets.
+ \snippet draganddrop/fridgemagnets/dragwidget.cpp 12
+ If the event has any other type, we call the event's
+ \l{QDragMoveEvent::}{ignore()} method allowing the event to be
+ propagated further.
+ \section1 Summary
+ We set our main widget's \l{QWidget::}{acceptDrops} property
+ and reimplemented QWidget's \l{QWidget::}{dragEnterEvent()},
+ \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
+ handlers to support content dropped on our widget.
+ In addition, we reimplemented the \l{QWidget::}{mousePressEvent()}
+ function to let the user pick up fridge magnets in the first place.
+ Because data is communicated using drag and drop operations and
+ encoded using MIME types, you can run more than one instance of this
+ example, and transfer magnets between them.