| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** 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 The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** 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: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example widgets/shapedclock |
| \title Shaped Clock Example |
| \ingroup examples-widgets |
| \brief The Shaped Clock example shows how to apply a translucent background |
| and a widget mask to a top-level widget to produce a shaped window. |
| |
| \borderedimage shapedclock-example.png |
| |
| Widget masks are used to customize the shapes of top-level widgets by |
| restricting the area available for painting and mouse input. Using a |
| translucent background facilitates partially transparent windows and smooth |
| edges. On most window systems, setting certain window flags will cause the |
| window decoration (title bar, window frame, buttons) to be disabled, |
| allowing specially-shaped windows to be created. In this example, we use |
| this feature to create a circular window containing an analog clock. |
| |
| Since this example's window does not provide a \uicontrol File menu or a close |
| button, we provide a context menu with an \uicontrol Exit entry so that the example |
| can be closed. Click the right mouse button over the window to open this menu. |
| |
| \section1 ShapedClock Class Definition |
| |
| The \c ShapedClock class is based on the \c AnalogClock class defined in the |
| \l{Analog Clock Example}{Analog Clock} example. The whole class definition is |
| presented below: |
| |
| \snippet widgets/shapedclock/shapedclock.h 0 |
| |
| The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as |
| that found in the \c AnalogClock class, with one important exception: we |
| now must also draw background (the clock face) ourselves, since the widget |
| background is just transparent. We implement \l{QWidget::sizeHint()}{sizeHint()} |
| so that we don't have to resize the widget explicitly. We also provide an event |
| handler for resize events. This allows us to update the mask if the clock is resized. |
| |
| Since the window containing the clock widget will have no title bar, we provide |
| implementations for \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} and |
| \l{QWidget::mousePressEvent()}{mousePressEvent()} to allow the clock to be dragged |
| around the screen. The \c dragPosition variable lets us keep track of where the user |
| last clicked on the widget. |
| |
| \section1 ShapedClock Class Implementation |
| |
| The \c ShapedClock constructor performs many of the same tasks as the \c AnalogClock |
| constructor. We set up a timer and connect it to the widget's update() slot: |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 0 |
| |
| We request a transparent window by setting the Qt::WA_TranslucentBackground |
| widget attribute. We inform the window manager that the widget is not to be |
| decorated with a window frame by setting the Qt::FramelessWindowHint flag |
| on the widget. As a result, we need to provide a way for the user to move |
| the clock around the screen. |
| |
| Mouse button events are delivered to the \c mousePressEvent() handler: |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 1 |
| |
| If the left mouse button is pressed over the widget, we record the displacement in |
| global (screen) coordinates between the top-left position of the widget's frame (even |
| when hidden) and the point where the mouse click occurred. This displacement will be |
| used if the user moves the mouse while holding down the left button. Since we acted |
| on the event, we accept it by calling its \l{QEvent::accept()}{accept()} function. |
| |
| \image shapedclock-dragging.png |
| |
| The \c mouseMoveEvent() handler is called if the mouse is moved over the widget. |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 2 |
| |
| If the left button is held down while the mouse is moved, the top-left corner of the |
| widget is moved to the point given by subtracting the \c dragPosition from the current |
| cursor position in global coordinates. If we drag the widget, we also accept the event. |
| |
| The \c paintEvent() function is mainly the same as described in the |
| \l{Analog Clock Example}{Analog Clock} example. The one addition is that we |
| use QPainter::drawEllipse() to draw a round clock face with the current |
| palette's default background color. We make the clock face a bit smaller |
| than the widget mask, so that the anti-aliased, semi-transparent pixels on |
| the edge are not clipped away by the widget mask. This gives the shaped |
| window smooth edges on the screen. |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 3 |
| |
| In the \c resizeEvent() handler, we re-use some of the code from the \c |
| paintEvent() to determine the region of the widget that is visible to the |
| user. This tells the system the area where mouse clicks should go to us, |
| and not to whatever window is behind us: |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 4 |
| |
| Since the clock face is a circle drawn in the center of the widget, this is the region |
| we use as the mask. |
| |
| Although the lack of a window frame may make it difficult for the user to resize the |
| widget on some platforms, it will not necessarily be impossible. The \c resizeEvent() |
| function ensures that the widget mask will always be updated if the widget's dimensions |
| change, and additionally ensures that it will be set up correctly when the widget is |
| first displayed. |
| |
| Finally, we implement the \c sizeHint() for the widget so that it is given a reasonable |
| default size when it is first shown: |
| |
| \snippet widgets/shapedclock/shapedclock.cpp 5 |
| |
| \section1 Notes on Widget Masks |
| |
| Widget masks are used to hint to the window system that the application |
| does not want mouse events for areas outside the mask. On most systems, |
| they also result in coarse visual clipping. To get smooth window edges, one |
| should use translucent background and anti-aliased painting, as shown in |
| this example. |
| |
| Since QRegion allows arbitrarily complex regions to be created, widget masks can be |
| made to suit the most unconventionally-shaped windows, and even allow widgets to be |
| displayed with holes in them. |
| |
| Widget masks can also be constructed by using the contents of pixmap to define the |
| opaque part of the widget. For a pixmap with an alpha channel, a suitable mask can be |
| obtained with QPixmap::mask(). |
| */ |