| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
|---|
| 4 | ** Contact: Qt Software Information (qt-info@nokia.com) | 
|---|
| 5 | ** | 
|---|
| 6 | ** This file is part of the documentation of the Qt Toolkit. | 
|---|
| 7 | ** | 
|---|
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
|---|
| 9 | ** Commercial Usage | 
|---|
| 10 | ** Licensees holding valid Qt Commercial licenses may use this file in | 
|---|
| 11 | ** accordance with the Qt Commercial License Agreement provided with the | 
|---|
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
|---|
| 13 | ** a written agreement between you and Nokia. | 
|---|
| 14 | ** | 
|---|
| 15 | ** GNU Lesser General Public License Usage | 
|---|
| 16 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
|---|
| 17 | ** General Public License version 2.1 as published by the Free Software | 
|---|
| 18 | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
|---|
| 19 | ** packaging of this file.  Please review the following information to | 
|---|
| 20 | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
|---|
| 21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | 
|---|
| 22 | ** | 
|---|
| 23 | ** In addition, as a special exception, Nokia gives you certain | 
|---|
| 24 | ** additional rights. These rights are described in the Nokia Qt LGPL | 
|---|
| 25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this | 
|---|
| 26 | ** 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. | 
|---|
| 35 | ** | 
|---|
| 36 | ** If you are unsure which license is appropriate for your use, please | 
|---|
| 37 | ** contact the sales department at qt-sales@nokia.com. | 
|---|
| 38 | ** $QT_END_LICENSE$ | 
|---|
| 39 | ** | 
|---|
| 40 | ****************************************************************************/ | 
|---|
| 41 |  | 
|---|
| 42 | /*! | 
|---|
| 43 | \example widgets/shapedclock | 
|---|
| 44 | \title Shaped Clock Example | 
|---|
| 45 |  | 
|---|
| 46 | The Shaped Clock example shows how to apply a widget mask to a top-level | 
|---|
| 47 | widget to produce a shaped window. | 
|---|
| 48 |  | 
|---|
| 49 | \image shapedclock-example.png | 
|---|
| 50 |  | 
|---|
| 51 | Widget masks are used to customize the shapes of top-level widgets by restricting | 
|---|
| 52 | the available area for painting. On some window systems, setting certain window flags | 
|---|
| 53 | will cause the window decoration (title bar, window frame, buttons) to be disabled, | 
|---|
| 54 | allowing specially-shaped windows to be created. In this example, we use this feature | 
|---|
| 55 | to create a circular window containing an analog clock. | 
|---|
| 56 |  | 
|---|
| 57 | Since this example's window does not provide a \gui File menu or a close | 
|---|
| 58 | button, we provide a context menu with an \gui Exit entry so that the example | 
|---|
| 59 | can be closed. Click the right mouse button over the window to open this menu. | 
|---|
| 60 |  | 
|---|
| 61 | \section1 ShapedClock Class Definition | 
|---|
| 62 |  | 
|---|
| 63 | The \c ShapedClock class is based on the \c AnalogClock class defined in the | 
|---|
| 64 | \l{Analog Clock Example}{Analog Clock} example. The whole class definition is | 
|---|
| 65 | presented below: | 
|---|
| 66 |  | 
|---|
| 67 | \snippet examples/widgets/shapedclock/shapedclock.h 0 | 
|---|
| 68 |  | 
|---|
| 69 | The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as that found | 
|---|
| 70 | in the \c AnalogClock class. We implement \l{QWidget::sizeHint()}{sizeHint()} | 
|---|
| 71 | so that we don't have to resize the widget explicitly. We also provide an event | 
|---|
| 72 | handler for resize events. This allows us to update the mask if the clock is resized. | 
|---|
| 73 |  | 
|---|
| 74 | Since the window containing the clock widget will have no title bar, we provide | 
|---|
| 75 | implementations for \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} and | 
|---|
| 76 | \l{QWidget::mousePressEvent()}{mousePressEvent()} to allow the clock to be dragged | 
|---|
| 77 | around the screen. The \c dragPosition variable lets us keep track of where the user | 
|---|
| 78 | last clicked on the widget. | 
|---|
| 79 |  | 
|---|
| 80 | \section1 ShapedClock Class Implementation | 
|---|
| 81 |  | 
|---|
| 82 | The \c ShapedClock constructor performs many of the same tasks as the \c AnalogClock | 
|---|
| 83 | constructor. We set up a timer and connect it to the widget's update() slot: | 
|---|
| 84 |  | 
|---|
| 85 | \snippet examples/widgets/shapedclock/shapedclock.cpp 0 | 
|---|
| 86 |  | 
|---|
| 87 | We inform the window manager that the widget is not to be decorated with a window | 
|---|
| 88 | frame by setting the Qt::FramelessWindowHint flag on the widget. As a result, we need | 
|---|
| 89 | to provide a way for the user to move the clock around the screen. | 
|---|
| 90 |  | 
|---|
| 91 | Mouse button events are delivered to the \c mousePressEvent() handler: | 
|---|
| 92 |  | 
|---|
| 93 | \snippet examples/widgets/shapedclock/shapedclock.cpp 1 | 
|---|
| 94 |  | 
|---|
| 95 | If the left mouse button is pressed over the widget, we record the displacement in | 
|---|
| 96 | global (screen) coordinates between the top-left position of the widget's frame (even | 
|---|
| 97 | when hidden) and the point where the mouse click occurred. This displacement will be | 
|---|
| 98 | used if the user moves the mouse while holding down the left button. Since we acted | 
|---|
| 99 | on the event, we accept it by calling its \l{QEvent::accept()}{accept()} function. | 
|---|
| 100 |  | 
|---|
| 101 | \image shapedclock-dragging.png | 
|---|
| 102 |  | 
|---|
| 103 | The \c mouseMoveEvent() handler is called if the mouse is moved over the widget. | 
|---|
| 104 |  | 
|---|
| 105 | \snippet examples/widgets/shapedclock/shapedclock.cpp 2 | 
|---|
| 106 |  | 
|---|
| 107 | If the left button is held down while the mouse is moved, the top-left corner of the | 
|---|
| 108 | widget is moved to the point given by subtracting the \c dragPosition from the current | 
|---|
| 109 | cursor position in global coordinates. If we drag the widget, we also accept the event. | 
|---|
| 110 |  | 
|---|
| 111 | The \c paintEvent() function is given for completeness. See the | 
|---|
| 112 | \l{Analog Clock Example}{Analog Clock} example for a description of the process used | 
|---|
| 113 | to render the clock. | 
|---|
| 114 |  | 
|---|
| 115 | \snippet examples/widgets/shapedclock/shapedclock.cpp 3 | 
|---|
| 116 |  | 
|---|
| 117 | In the \c resizeEvent() handler, we re-use some of the code from the \c paintEvent() | 
|---|
| 118 | to determine the region of the widget that is visible to the user: | 
|---|
| 119 |  | 
|---|
| 120 | \snippet examples/widgets/shapedclock/shapedclock.cpp 4 | 
|---|
| 121 |  | 
|---|
| 122 | Since the clock face is a circle drawn in the center of the widget, this is the region | 
|---|
| 123 | we use as the mask. | 
|---|
| 124 |  | 
|---|
| 125 | Although the lack of a window frame may make it difficult for the user to resize the | 
|---|
| 126 | widget on some platforms, it will not necessarily be impossible. The \c resizeEvent() | 
|---|
| 127 | function ensures that the widget mask will always be updated if the widget's dimensions | 
|---|
| 128 | change, and additionally ensures that it will be set up correctly when the widget is | 
|---|
| 129 | first displayed. | 
|---|
| 130 |  | 
|---|
| 131 | Finally, we implement the \c sizeHint() for the widget so that it is given a reasonable | 
|---|
| 132 | default size when it is first shown: | 
|---|
| 133 |  | 
|---|
| 134 | \snippet examples/widgets/shapedclock/shapedclock.cpp 5 | 
|---|
| 135 |  | 
|---|
| 136 | \section1 Notes on Widget Masks | 
|---|
| 137 |  | 
|---|
| 138 | Since QRegion allows arbitrarily complex regions to be created, widget masks can be | 
|---|
| 139 | made to suit the most unconventionally-shaped windows, and even allow widgets to be | 
|---|
| 140 | displayed with holes in them. | 
|---|
| 141 |  | 
|---|
| 142 | Widget masks can also be constructed by using the contents of pixmap to define the | 
|---|
| 143 | opaque part of the widget. For a pixmap with an alpha channel, a suitable mask can be | 
|---|
| 144 | obtained with QPixmap::mask(). | 
|---|
| 145 | */ | 
|---|