summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-05-15 16:30:25 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-05-16 13:37:38 +0200
commit8e94af2ed0577936cabaffab336014c1be9002af (patch)
treee058a5431475f91d07fcaeab3344d39508b1210d
parent322387ce7b5e768d6bd0b8dda1b8f9b704e88f47 (diff)
downloadqtbase-8e94af2ed0577936cabaffab336014c1be9002af.tar.gz
Revamp the shapedclock example
Rename it to "Translucent Background", as that's what the example shows how to do. And modern applications shouldn't use a (binary) mask to create shaped windows. Instead, set the TranslucentBackground attribute, don't paint pixels that should be fully transparent and use anti-aliased or semi-opaque painting for pixels that should be translucent. Adjust the example and documentation accordingly. Move the statment that widget masks create coarse visual clipping to the QWidget::setMask documentation. Pick-to: 6.5 Change-Id: Id49d854093f2cb471afb178d32723081c7543543 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r--examples/widgets/doc/src/shapedclock.qdoc73
-rw-r--r--examples/widgets/widgets/shapedclock/shapedclock.cpp14
-rw-r--r--examples/widgets/widgets/shapedclock/shapedclock.h1
-rw-r--r--src/widgets/kernel/qwidget.cpp16
4 files changed, 34 insertions, 70 deletions
diff --git a/examples/widgets/doc/src/shapedclock.qdoc b/examples/widgets/doc/src/shapedclock.qdoc
index 4ce341266a..8e69be1db4 100644
--- a/examples/widgets/doc/src/shapedclock.qdoc
+++ b/examples/widgets/doc/src/shapedclock.qdoc
@@ -3,17 +3,18 @@
/*!
\example widgets/shapedclock
- \title Shaped Clock Example
+ \title Translucent Background
\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.
+ \brief The example shows how to make a round window with a translucent
+ background.
\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
+ Widgets that set their background to be translucent will be transparent for all
+ unpainted pixels, and the background will shine through pixels painted with an
+ opacity of less than 100%. Pixels that are not painted at all will also not
+ receive any mouse input. This can be used to customize the shapes of top-level
+ widgets. 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.
@@ -30,12 +31,10 @@
\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.
+ The \l{QWidget::paintEvent()}{paintEvent()} implementation draws an analog clock
+ on a semi-transparent background (the clock face). In addition, we implement
+ \l{QWidget::sizeHint()}{sizeHint()} so that we don't have to resize the widget
+ explicitly.
Since the window containing the clock widget will have no title bar, we provide
implementations for \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} and
@@ -45,8 +44,9 @@
\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:
+ The \c ShapedClock constructor sets up a timer and connect it to the widget's
+ update() slot. In addition, we add an action to the widget, which will automatically
+ become available through a context menu when right-clicking on the widget.
\snippet widgets/shapedclock/shapedclock.cpp 0
@@ -77,49 +77,14 @@
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. 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.
+ \l{Analog Clock} example. The one addition is that we use QPainter::drawEllipse() to
+ draw a round clock face. We reduce the painter's opacity to 90%, and use the palette's
+ default background color.
\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().
+ \snippet widgets/shapedclock/shapedclock.cpp 4
*/
diff --git a/examples/widgets/widgets/shapedclock/shapedclock.cpp b/examples/widgets/widgets/shapedclock/shapedclock.cpp
index 5cc4a54016..25225eb5b6 100644
--- a/examples/widgets/widgets/shapedclock/shapedclock.cpp
+++ b/examples/widgets/widgets/shapedclock/shapedclock.cpp
@@ -78,7 +78,9 @@ void ShapedClock::paintEvent(QPaintEvent *)
painter.setPen(Qt::NoPen);
painter.setBrush(palette().window());
+ painter.setOpacity(0.9);
painter.drawEllipse(QPoint(0, 0), 98, 98);
+ painter.setOpacity(1.0);
painter.setPen(Qt::NoPen);
painter.setBrush(hourColor);
@@ -114,18 +116,8 @@ void ShapedClock::paintEvent(QPaintEvent *)
//! [3]
//! [4]
-void ShapedClock::resizeEvent(QResizeEvent * /* event */)
-{
- int side = qMin(width(), height());
- QRegion maskedRegion(width() / 2 - side / 2, height() / 2 - side / 2, side,
- side, QRegion::Ellipse);
- setMask(maskedRegion);
-}
-//! [4]
-
-//! [5]
QSize ShapedClock::sizeHint() const
{
return QSize(200, 200);
}
-//! [5]
+//! [4]
diff --git a/examples/widgets/widgets/shapedclock/shapedclock.h b/examples/widgets/widgets/shapedclock/shapedclock.h
index c359a3a083..3dec93cc74 100644
--- a/examples/widgets/widgets/shapedclock/shapedclock.h
+++ b/examples/widgets/widgets/shapedclock/shapedclock.h
@@ -19,7 +19,6 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
- void resizeEvent(QResizeEvent *event) override;
private:
QPoint dragPosition;
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index d0ad169024..1b8e9890b5 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -10233,7 +10233,7 @@ void QWidget::ensurePolished() const
Returns the mask currently set on a widget. If no mask is set the
return value will be an empty region.
- \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
+ \sa setMask(), clearMask(), QRegion::isEmpty()
*/
QRegion QWidget::mask() const
{
@@ -12964,8 +12964,16 @@ QPainter *QWidget::sharedPainter() const
widget, window system controls in that area may or may not be
visible, depending on the platform.
- Note that this effect can be slow if the region is particularly
- complex.
+ 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. Note that this
+ effect can be slow if the region is particularly complex.
+
+ 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, use
+ translucent background and anti-aliased painting instead, as shown in the
+ \l{Translucent Background} example.
\sa windowOpacity
*/
@@ -13051,7 +13059,7 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
Masked widgets receive mouse events only on their visible
portions.
- \sa clearMask(), windowOpacity(), {Shaped Clock Example}
+ \sa clearMask(), windowOpacity()
*/
void QWidget::setMask(const QBitmap &bitmap)
{