| /**************************************************************************** |
| ** |
| ** 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 2dpainting |
| \title 2D Painting Example |
| \ingroup examples-widgets-opengl |
| |
| \brief The 2D Painting example shows how QPainter and QOpenGLWidget can be |
| used together to display accelerated 2D graphics on supported hardware. |
| |
| \image 2dpainting-example.png |
| |
| The QPainter class is used to draw 2D graphics primitives onto |
| paint devices provided by QPaintDevice subclasses, such as QWidget |
| and QImage. |
| |
| Since QOpenGLWidget is a subclass of QWidget, it is possible |
| to reimplement its \l{QWidget::paintEvent()}{paintEvent()} and use |
| QPainter to draw on the device, just as you would with a QWidget. |
| The only difference is that the painting operations will be accelerated |
| in hardware if it is supported by your system's OpenGL drivers. |
| |
| In this example, we perform the same painting operations on a |
| QWidget and a QOpenGLWidget. The QWidget is shown with anti-aliasing |
| enabled, and the QOpenGLWidget will also use anti-aliasing if the |
| required extensions are supported by your system's OpenGL driver. |
| |
| \section1 Overview |
| |
| To be able to compare the results of painting onto a QOpenGLWidget subclass |
| with native drawing in a QWidget subclass, we want to show both kinds |
| of widget side by side. To do this, we derive subclasses of QWidget and |
| QOpenGLWidget, using a separate \c Helper class to perform the same painting |
| operations for each, and lay them out in a top-level widget, itself |
| provided a the \c Window class. |
| |
| \section1 Helper Class Definition |
| |
| In this example, the painting operations are performed by a helper class. |
| We do this because we want the same painting operations to be performed |
| for both our QWidget subclass and the QOpenGLWidget subclass. |
| |
| The \c Helper class is minimal: |
| |
| \snippet 2dpainting/helper.h 0 |
| |
| Apart from the constructor, it only provides a \c paint() function to paint |
| using a painter supplied by one of our widget subclasses. |
| |
| \section1 Helper Class Implementation |
| |
| The constructor of the class sets up the resources it needs to paint |
| content onto a widget: |
| |
| \snippet 2dpainting/helper.cpp 0 |
| |
| The actual painting is performed in the \c paint() function. This takes |
| a QPainter that has already been set up to paint onto a paint device |
| (either a QWidget or a QOpenGLWidget), a QPaintEvent that provides information |
| about the region to be painted, and a measure of the elapsed time (in |
| milliseconds) since the paint device was last updated. |
| |
| \snippet 2dpainting/helper.cpp 1 |
| |
| We begin painting by filling in the region contained in the paint event |
| before translating the origin of the coordinate system so that the rest |
| of the painting operations will be displaced towards the center of the |
| paint device. |
| |
| We draw a spiral pattern of circles, using the elapsed time specified to |
| animate them so that they appear to move outward and around the coordinate |
| system's origin: |
| |
| \snippet 2dpainting/helper.cpp 2 |
| |
| Since the coordinate system is rotated many times during |
| this process, we \l{QPainter::save()}{save()} the QPainter's state |
| beforehand and \l{QPainter::restore()}{restore()} it afterwards. |
| |
| \snippet 2dpainting/helper.cpp 3 |
| |
| We draw some text at the origin to complete the effect. |
| |
| \section1 Widget Class Definition |
| |
| The \c Widget class provides a basic custom widget that we use to |
| display the simple animation painted by the \c Helper class. |
| |
| \snippet 2dpainting/widget.h 0 |
| |
| Apart from the constructor, it only contains a |
| \l{QWidget::paintEvent()}{paintEvent()} function, that lets us draw |
| customized content, and a slot that is used to animate its contents. |
| One member variable keeps track of the \c Helper that the widget uses |
| to paint its contents, and the other records the elapsed time since |
| it was last updated. |
| |
| \section1 Widget Class Implementation |
| |
| The constructor only initializes the member variables, storing the |
| \c Helper object supplied and calling the base class's constructor, |
| and enforces a fixed size for the widget: |
| |
| \snippet 2dpainting/widget.cpp 0 |
| |
| The \c animate() slot is called whenever a timer, which we define later, times |
| out: |
| |
| \snippet 2dpainting/widget.cpp 1 |
| |
| Here, we determine the interval that has elapsed since the timer last |
| timed out, and we add it to any existing value before repainting the |
| widget. Since the animation used in the \c Helper class loops every second, |
| we can use the modulo operator to ensure that the \c elapsed variable is |
| always less than 1000. |
| |
| Since the \c Helper class does all of the actual painting, we only have |
| to implement a paint event that sets up a QPainter for the widget and calls |
| the helper's \c paint() function: |
| |
| \snippet 2dpainting/widget.cpp 2 |
| |
| \section1 GLWidget Class Definition |
| |
| The \c GLWidget class definition is basically the same as the \c Widget |
| class except that it is derived from QOpenGLWidget. |
| |
| \snippet 2dpainting/glwidget.h 0 |
| |
| Again, the member variables record the \c Helper used to paint the |
| widget and the elapsed time since the previous update. |
| |
| \section1 GLWidget Class Implementation |
| |
| The constructor differs a little from the \c Widget class's constructor: |
| |
| \snippet 2dpainting/glwidget.cpp 0 |
| |
| As well as initializing the \c elapsed member variable and storing the |
| \c Helper object used to paint the widget, the base class's constructor |
| is called with the format that specifies the \l QGL::SampleBuffers flag. |
| This enables anti-aliasing if it is supported by your system's OpenGL |
| driver. |
| |
| The \c animate() slot is exactly the same as that provided by the \c Widget |
| class: |
| |
| \snippet 2dpainting/glwidget.cpp 1 |
| |
| The \c paintEvent() is almost the same as that found in the \c Widget class: |
| |
| \snippet 2dpainting/glwidget.cpp 2 |
| |
| Since anti-aliasing will be enabled if available, we only need to set up |
| a QPainter on the widget and call the helper's \c paint() function to display |
| the widget's contents. |
| |
| \section1 Window Class Definition |
| |
| The \c Window class has a basic, minimal definition: |
| |
| \snippet 2dpainting/window.h 0 |
| |
| It contains a single \c Helper object that will be shared between all |
| widgets. |
| |
| \section1 Window Class Implementation |
| |
| The constructor does all the work, creating a widget of each type and |
| inserting them with labels into a layout: |
| |
| \snippet 2dpainting/window.cpp 0 |
| |
| A timer with a 50 millisecond time out is constructed for animation purposes, |
| and connected to the \c animate() slots of the \c Widget and \c GLWidget objects. |
| Once started, the widgets should be updated at around 20 frames per second. |
| |
| \section1 Running the Example |
| |
| The example shows the same painting operations performed at the same time |
| in a \c Widget and a \c GLWidget. The quality and speed of rendering in the |
| \c GLWidget depends on the level of support for multisampling and hardware |
| acceleration that your system's OpenGL driver provides. If support for either |
| of these is lacking, the driver may fall back on a software renderer that |
| may trade quality for speed. |
| */ |