Refurbish the clock example

Fixes: QTBUG-118871
Pick-to: 6.6
Change-Id: I0a1a6444cb381d49adbc39e73d7862c9cfe61dce
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Matthias Rauter 2023-11-09 15:11:50 +01:00
parent ea84c1a229
commit 619ec1a640
4 changed files with 91 additions and 63 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

@ -20,8 +20,8 @@
\section1 AnalogClock Class Definition \section1 AnalogClock Class Definition
The \c AnalogClock class provides a clock widget with hour and minute The \c AnalogClock class provides a clock widget with hour, minute and
hands that is automatically updated every few seconds. second hands that is automatically updated every second.
We subclass \l QWidget and reimplement the standard We subclass \l QWidget and reimplement the standard
\l{QWidget::paintEvent()}{paintEvent()} function to draw the clock face: \l{QWidget::paintEvent()}{paintEvent()} function to draw the clock face:
@ -29,19 +29,14 @@
\section1 AnalogClock Class Implementation \section1 AnalogClock Class Implementation
\snippet widgets/analogclock/analogclock.cpp 1
When the widget is constructed, we set up a one-second timer to When the widget is constructed, we set up a one-second timer to
keep track of the current time, and we connect it to the standard keep track of the current time, and we connect it to the standard
\l{QWidget::update()}{update()} slot so that the clock face is \l{QWidget::update()}{update()} slot so that the clock face is
updated when the timer emits the \l{QTimer::timeout()}{timeout()} updated when the timer emits the \l{QTimer::timeout()}{timeout()}
signal. signal. Finally, we resize the widget so that it is displayed at a
Finally, we resize the widget so that it is displayed at a
reasonable size. reasonable size.
\snippet widgets/analogclock/analogclock.cpp 8 \snippet widgets/analogclock/analogclock.cpp 1
\snippet widgets/analogclock/analogclock.cpp 10
The \c paintEvent() function is called whenever the widget's The \c paintEvent() function is called whenever the widget's
contents need to be updated. This happens when the widget is contents need to be updated. This happens when the widget is
@ -49,31 +44,37 @@
executed when the widget's \l{QWidget::update()}{update()} slot executed when the widget's \l{QWidget::update()}{update()} slot
is called. Since we connected the timer's is called. Since we connected the timer's
\l{QTimer::timeout()}{timeout()} signal to this slot, it will be \l{QTimer::timeout()}{timeout()} signal to this slot, it will be
called at least once every five seconds. called at least once per second.
Before we set up the painter and draw the clock, we first define Before we set up the painter and draw the clock, we first define
two lists of \l {QPoint}s and two \l{QColor}s that will be used three lists of \l {QPoint}s and three \l{QColor}s that will be used
for the hour and minute hands. The minute hand's color has an for the hour, minute and second hands. We use the
alpha component of 191, meaning that it's 75% opaque. \l{QWidget::palette()}{palette()} function to get appropriate colors
that fit into the rest of the window, both in light and dark mode.
The hour and minute hands are drawn in the foreground color, the
second hand is drawn in the accent color.
We also determine the length of the widget's shortest side so that we We also determine the length of the widget's shortest side so that we
can fit the clock face inside the widget. It is also useful to determine can fit the clock face inside the widget. It is also useful to determine
the current time before we start drawing. the current time before we start drawing.
\snippet widgets/analogclock/analogclock.cpp 11 \snippet widgets/analogclock/analogclock.cpp 8
\snippet widgets/analogclock/analogclock.cpp 12 \snippet widgets/analogclock/analogclock.cpp 10
\snippet widgets/analogclock/analogclock.cpp 13
\snippet widgets/analogclock/analogclock.cpp 14
The contents of custom widgets are drawn with a QPainter. The contents of custom widgets are drawn with a QPainter.
Painters can be used to draw on any QPaintDevice, but they are Painters can be used to draw on any QPaintDevice, but they are
usually used with widgets, so we pass the widget instance to the usually used with widgets, so we pass the widget instance to the
painter's constructor. painter's constructor.
\snippet widgets/analogclock/analogclock.cpp 11
\snippet widgets/analogclock/analogclock.cpp 14
We call QPainter::setRenderHint() with QPainter::Antialiasing to We call QPainter::setRenderHint() with QPainter::Antialiasing to
turn on antialiasing. This makes drawing of diagonal lines much turn on antialiasing. This makes drawing of diagonal lines much
smoother. smoother.
\snippet widgets/analogclock/analogclock.cpp 12
The translation moves the origin to the center of the widget, and The translation moves the origin to the center of the widget, and
the scale operation ensures that the following drawing operations the scale operation ensures that the following drawing operations
are scaled to fit within the widget. We use a scale factor that are scaled to fit within the widget. We use a scale factor that
@ -81,6 +82,8 @@
ensures that these lie within the length of the widget's shortest ensures that these lie within the length of the widget's shortest
side. side.
\snippet widgets/analogclock/analogclock.cpp 13
To make our code simpler, we will draw a fixed size clock face that will To make our code simpler, we will draw a fixed size clock face that will
be positioned and scaled so that it lies in the center of the widget. be positioned and scaled so that it lies in the center of the widget.
@ -91,44 +94,47 @@
\image analogclock-viewport.png \image analogclock-viewport.png
We draw the hour hand first, using a formula that rotates the coordinate
system counterclockwise by a number of degrees determined by the current
hour and minute. This means that the hand will be shown rotated clockwise
by the required amount.
\snippet widgets/analogclock/analogclock.cpp 15
\snippet widgets/analogclock/analogclock.cpp 16
We set the pen to be Qt::NoPen because we don't want any outline, We set the pen to be Qt::NoPen because we don't want any outline,
and we use a solid brush with the color appropriate for and we use a solid brush with the color appropriate for
displaying hours. Brushes are used when filling in polygons and displaying hours. Brushes are used when filling in polygons and
other geometric shapes. other geometric shapes.
\snippet widgets/analogclock/analogclock.cpp 17 \snippet widgets/analogclock/analogclock.cpp 15
\snippet widgets/analogclock/analogclock.cpp 19 \snippet widgets/analogclock/analogclock.cpp 16
We draw the hour hand first, using a formula that rotates the coordinate
system counterclockwise by a number of degrees determined by the current
hour and minute. This means that the hand will be shown rotated clockwise
by the required amount.
We save and restore the transformation matrix before and after the We save and restore the transformation matrix before and after the
rotation because we want to place the minute hand without having to rotation because we want to place the minute hand without having to
take into account any previous rotations. take into account any previous rotations.
\snippet widgets/analogclock/analogclock.cpp 17
\snippet widgets/analogclock/analogclock.cpp 19
We draw markers around the edge of the clock for each hour in the same
color as the hour hand. We draw each marker then rotate the coordinate
system so that the painter is ready for the next one.
\snippet widgets/analogclock/analogclock.cpp 20 \snippet widgets/analogclock/analogclock.cpp 20
\codeline
The minute hand is rotated and painted in a similar way to the hour hand.
\snippet widgets/analogclock/analogclock.cpp 21 \snippet widgets/analogclock/analogclock.cpp 21
We draw markers around the edge of the clock for each hour. We For the seconds hand we do the same and add two cicles as a visual highlight.
draw each marker then rotate the coordinate system so that the
painter is ready for the next one.
\snippet widgets/analogclock/analogclock.cpp 22
\snippet widgets/analogclock/analogclock.cpp 23 \snippet widgets/analogclock/analogclock.cpp 23
\codeline
\snippet widgets/analogclock/analogclock.cpp 24
The minute hand is rotated in a similar way to the hour hand. Finally, we draw markers around the edge of the clock, indicating
minutes and seconds. This time we draw them as lines and therefore
set the pen to the respective color.
\snippet widgets/analogclock/analogclock.cpp 25 \snippet widgets/analogclock/analogclock.cpp 25
\codeline \codeline
\snippet widgets/analogclock/analogclock.cpp 26 \snippet widgets/analogclock/analogclock.cpp 27
Again, we draw markers around the edge of the clock, but this
time to indicate minutes. We skip multiples of 5 to avoid drawing
minute markers on top of hour markers.
*/ */

View File

@ -31,19 +31,29 @@ AnalogClock::AnalogClock(QWidget *parent)
void AnalogClock::paintEvent(QPaintEvent *) void AnalogClock::paintEvent(QPaintEvent *)
//! [8] //! [10] //! [8] //! [10]
{ {
static const QPoint hourHand[3] = { static const QPoint hourHand[4] = {
QPoint(7, 8), QPoint(5, 14),
QPoint(-7, 8), QPoint(-5, 14),
QPoint(0, -40) QPoint(-4, -71),
QPoint(4, -71)
}; };
static const QPoint minuteHand[3] = { static const QPoint minuteHand[4] = {
QPoint(7, 8), QPoint(4, 14),
QPoint(-7, 8), QPoint(-4, 14),
QPoint(0, -70) QPoint(-3, -89),
QPoint(3, -89)
}; };
QColor hourColor(127, 0, 127); static const QPoint secondsHand[4] = {
QColor minuteColor(0, 127, 127, 191); QPoint(1, 14),
QPoint(-1, 14),
QPoint(-1, -89),
QPoint(1, -89)
};
const QColor hourColor(palette().color(QPalette::Text));
const QColor minuteColor(palette().color(QPalette::Text));
const QColor secondsColor(palette().color(QPalette::Accent));
int side = qMin(width(), height()); int side = qMin(width(), height());
//! [10] //! [10]
@ -54,9 +64,12 @@ void AnalogClock::paintEvent(QPaintEvent *)
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
//! [12] //! [13] //! [12] //! [13]
painter.translate(width() / 2, height() / 2); painter.translate(width() / 2, height() / 2);
//! [13] //! [14]
painter.scale(side / 200.0, side / 200.0); painter.scale(side / 200.0, side / 200.0);
//! [9] //! [14] //! [9] //! [13]
//! [14]
QTime time = QTime::currentTime();
//! [14]
//! [15] //! [15]
painter.setPen(Qt::NoPen); painter.setPen(Qt::NoPen);
@ -64,36 +77,45 @@ void AnalogClock::paintEvent(QPaintEvent *)
painter.setBrush(hourColor); painter.setBrush(hourColor);
//! [16] //! [16]
//! [18] //! [18]
QTime time = QTime::currentTime();
//! [17] //! [17]
painter.save(); painter.save();
//! [17] //! [19] //! [17] //! [19]
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 3); painter.drawConvexPolygon(hourHand, 4);
painter.restore(); painter.restore();
//! [18] //! [19] //! [18] //! [19]
//! [20] //! [20]
painter.setPen(hourColor);
//! [20] //! [21]
for (int i = 0; i < 12; ++i) { for (int i = 0; i < 12; ++i) {
painter.drawLine(88, 0, 96, 0); painter.drawRect(73, -3, 16, 6);
painter.rotate(30.0); painter.rotate(30.0);
} }
//! [20]
//! [21] //! [21]
painter.setBrush(minuteColor);
//! [22] //! [22]
painter.setPen(Qt::NoPen); painter.save();
//! [22] //! [23] painter.rotate(6.0 * time.minute());
painter.setBrush(minuteColor); painter.drawConvexPolygon(minuteHand, 4);
painter.restore();
//! [21] //! [22]
//! [23]
painter.setBrush(secondsColor);
//! [23]
//! [24] //! [24]
painter.save(); painter.save();
painter.rotate(6.0 * (time.minute() + time.second() / 60.0)); painter.rotate(6.0 * time.second());
painter.drawConvexPolygon(minuteHand, 3); painter.drawConvexPolygon(secondsHand, 4);
painter.drawEllipse(-3, -3, 6, 6);
painter.drawEllipse(-5, -68, 10, 10);
painter.restore(); painter.restore();
//! [23] //! [24] //! [24]
//! [25] //! [25]
painter.setPen(minuteColor); painter.setPen(minuteColor);
@ -101,10 +123,10 @@ void AnalogClock::paintEvent(QPaintEvent *)
//! [27] //! [27]
for (int j = 0; j < 60; ++j) { for (int j = 0; j < 60; ++j) {
if ((j % 5) != 0) painter.drawLine(92, 0, 96, 0);
painter.drawLine(92, 0, 96, 0);
painter.rotate(6.0); painter.rotate(6.0);
} }
//! [27] //! [27]
} }
//! [26] //! [26]