| /**************************************************************************** |
| ** |
| ** 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/wiggly |
| \title Wiggly Example |
| \ingroup examples-widgets |
| \brief The Wiggly example shows how to animate a widget using |
| QBasicTimer and \l{QObject::timerEvent()}{timerEvent()}. In |
| addition, the example demonstrates how to use QFontMetrics to |
| determine the size of text on screen. |
| |
| \borderedimage wiggly-example.png |
| \caption Screenshot of the Wiggly example |
| |
| QBasicTimer is a low-level class for timers. Unlike QTimer, |
| QBasicTimer doesn't inherit from QObject; instead of emitting a |
| \l{QTimer::timeout()}{timeout()} signal when a certain amount of |
| time has passed, it sends a QTimerEvent to a QObject of our |
| choice. This makes QBasicTimer a more lightweight alternative to |
| QTimer. Qt's built-in widgets use it internally, and it is |
| provided in Qt's API for highly-optimized applications (such as |
| embedded applications). |
| |
| The example consists of two classes: |
| |
| \list |
| \li \c WigglyWidget is the custom widget displaying the text |
| in a wiggly line. |
| |
| \li \c Dialog is the dialog widget allowing the user to enter a |
| text. It combines a \c WigglyWidget and a \c QLineEdit. |
| \endlist |
| |
| We will first take a quick look at the \c Dialog class, then we |
| will review the \c WigglyWidget class. |
| |
| \section1 Dialog Class Definition |
| |
| \snippet widgets/wiggly/dialog.h 0 |
| |
| The \c Dialog class provides a dialog widget that allows the user |
| to enter a text. The text is then rendered by \c WigglyWidget. |
| |
| \section1 Dialog Class Implementation |
| |
| \snippet widgets/wiggly/dialog.cpp 0 |
| |
| In the constructor we create a wiggly widget along with a |
| \l{QLineEdit}{line edit}, and we put the two widgets in a |
| vertical layout. We connect the line edit's \l |
| {QLineEdit::textChanged()}{textChanged()} signal to the wiggly |
| widget's \c setText() slot to obtain the real time interaction |
| with the wiggly widget. The widget's default text is "Hello |
| world!". |
| |
| \section1 WigglyWidget Class Definition |
| |
| \snippet widgets/wiggly/wigglywidget.h 0 |
| |
| The \c WigglyWidget class provides the wiggly line displaying the |
| text. We subclass QWidget and reimplement the standard \l |
| {QWidget::paintEvent()}{paintEvent()} and \l |
| {QObject::timerEvent()}{timerEvent()} functions to draw and update |
| the widget. In addition we implement a public \c setText() slot |
| that sets the widget's text. |
| |
| The \c timer variable, of type QBasicTimer, is used to update the |
| widget at regular intervals, making the widget move. The \c text |
| variable is used to store the currently displayed text, and \c |
| step to calculate position and color for each character on the |
| wiggly line. |
| |
| \section1 WigglyWidget Class Implementation |
| |
| \snippet widgets/wiggly/wigglywidget.cpp 0 |
| |
| In the constructor, we make the widget's background slightly |
| lighter than the usual background using the QPalette::Midlight |
| color role. The background role defines the brush from the |
| widget's palette that Qt uses to paint the background. Then we |
| enlarge the widget's font with 20 points. |
| |
| Finally we start the timer; the call to QBasicTimer::start() |
| makes sure that \e this particular wiggly widget will receive the |
| timer events generated when the timer times out (every 60 |
| milliseconds). |
| |
| \snippet widgets/wiggly/wigglywidget.cpp 1 |
| \snippet widgets/wiggly/wigglywidget.cpp 2 |
| |
| The \c paintEvent() function is called whenever a QPaintEvent is |
| sent to the widget. Paint events are sent to widgets that need to |
| update themselves, for instance when part of a widget is exposed |
| because a covering widget was moved. For the wiggly widget, a |
| paint event will also be generated every 60 milliseconds from |
| the \c timerEvent() slot. |
| |
| The \c sineTable represents y-values of the sine curve, |
| multiplied by 100. It is used to make the wiggly widget move |
| along the sine curve. |
| |
| The QFontMetrics object provides information about the widget's |
| font. The \c x variable is the horizontal position where we start |
| drawing the text. The \c y variable is the vertical position of |
| the text's base line. Both variables are computed so that the |
| text is horizontally and vertically centered. To compute the base |
| line, we take into account the font's ascent (the height of the |
| font above the base line) and font's descent (the height of the |
| font below the base line). If the descent equals the ascent, they |
| cancel out each other and the base line is at \c height() / 2. |
| |
| \snippet widgets/wiggly/wigglywidget.cpp 3 |
| \snippet widgets/wiggly/wigglywidget.cpp 4 |
| |
| Each time the \c paintEvent() function is called, we create a |
| QPainter object \c painter to draw the contents of the widget. |
| For each character in \c text, we determine the color and the |
| position on the wiggly line based on \c step. In addition, \c x |
| is incremented by the character's width. |
| |
| For simplicity, we assume that QFontMetrics::horizontalAdvance(\c text) |
| returns the sum of the individual character advances |
| (QFontMetrics::horizontalAdvance(\c text[i])). In practice, this is not |
| always the case because QFontMetrics::horizontalAdvance(\c text) also takes |
| into account the kerning between certain letters (e.g., 'A' and |
| 'V'). The result is that the text isn't perfectly centered. You |
| can verify this by typing "AVAVAVAVAVAV" in the line edit. |
| |
| \snippet widgets/wiggly/wigglywidget.cpp 5 |
| \snippet widgets/wiggly/wigglywidget.cpp 6 |
| |
| The \c timerEvent() function receives all the timer events that |
| are generated for this widget. If a timer event is sent from the |
| widget's QBasicTimer, we increment \c step to make the text move, |
| and call QWidget::update() to refresh the display. Any other |
| timer event is passed on to the base class's implementation of |
| the \l{QWidget::timerEvent()}{timerEvent()} function. |
| |
| The QWidget::update() slot does not cause an immediate repaint; |
| instead the slot schedules a paint event for processing when Qt |
| returns to the main event loop. The paint events are then handled |
| by \c{WigglyWidget}'s \c paintEvent() function. |
| */ |