| /**************************************************************************** |
| ** |
| ** 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 painting/transformations |
| \title Transformations Example |
| \ingroup examples-painting |
| \brief The Transformations example shows how transformations |
| influence the way that QPainter renders graphics primitives. |
| |
| \brief The Transformations example shows how transformations influence |
| the way that QPainter renders graphics primitives. In particular |
| it shows how the order of transformations affect the result. |
| |
| \image transformations-example.png |
| |
| The application allows the user to manipulate the rendering of a |
| shape by changing the translation, rotation and scale of |
| QPainter's coordinate system. |
| |
| The example consists of two classes and a global enum: |
| |
| \list |
| \li The \c RenderArea class controls the rendering of a given shape. |
| \li The \c Window class is the application's main window. |
| \li The \c Operation enum describes the various transformation |
| operations available in the application. |
| \endlist |
| |
| First we will take a quick look at the \c Operation enum, then we |
| will review the \c RenderArea class to see how a shape is |
| rendered. Finally, we will take a look at the Transformations |
| application's features implemented in the \c Window class. |
| |
| \section1 Transformation Operations |
| |
| Normally, the QPainter operates on the associated device's own |
| coordinate system, but it also has good support for coordinate |
| transformations. |
| |
| The default coordinate system of a paint device has its origin at |
| the top-left corner. The x values increase to the right and the y |
| values increase downwards. You can scale the coordinate system by |
| a given offset using the QPainter::scale() function, you can |
| rotate it clockwise using the QPainter::rotate() function and you |
| can translate it (i.e. adding a given offset to the points) using |
| the QPainter::translate() function. You can also twist the |
| coordinate system around the origin (called shearing) using the |
| QPainter::shear() function. |
| |
| All the tranformation operations operate on QPainter's |
| tranformation matrix that you can retrieve using the |
| QPainter::worldTransform() function. A matrix transforms a point in the |
| plane to another point. For more information about the |
| transformation matrix, see the \l {Coordinate System} and |
| QTransform documentation. |
| |
| \snippet painting/transformations/renderarea.h 0 |
| |
| The global \c Operation enum is declared in the \c renderarea.h |
| file and describes the various transformation operations available |
| in the Transformations application. |
| |
| \section1 RenderArea Class Definition |
| |
| The \c RenderArea class inherits QWidget, and controls the |
| rendering of a given shape. |
| |
| \snippet painting/transformations/renderarea.h 1 |
| |
| We declare two public functions, \c setOperations() and |
| \c setShape(), to be able to specify the \c RenderArea widget's shape |
| and to transform the coordinate system the shape is rendered |
| within. |
| |
| We reimplement the QWidget's \l |
| {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l |
| {QWidget::sizeHint()}{sizeHint()} functions to give the \c |
| RenderArea widget a reasonable size within our application, and we |
| reimplement the QWidget::paintEvent() event handler to draw the |
| render area's shape applying the user's transformation choices. |
| |
| \snippet painting/transformations/renderarea.h 2 |
| |
| We also declare several convenience functions to draw the shape, |
| the coordinate system's outline and the coordinates, and to |
| transform the painter according to the chosen transformations. |
| |
| In addition, the \c RenderArea widget keeps a list of the |
| currently applied transformation operations, a reference to its |
| shape, and a couple of convenience variables that we will use when |
| rendering the coordinates. |
| |
| \section1 RenderArea Class Implementation |
| |
| The \c RenderArea widget controls the rendering of a given shape, |
| including the transformations of the coordinate system, by |
| reimplementing the QWidget::paintEvent() event handler. But first |
| we will take a quick look at the constructor and at the functions |
| that provides access to the \c RenderArea widget: |
| |
| \snippet painting/transformations/renderarea.cpp 0 |
| |
| In the constructor we pass the parent parameter on to the base |
| class, and customize the font that we will use to render the |
| coordinates. The QWidget::font() function returns the font |
| currently set for the widget. As long as no special font has been |
| set, or after QWidget::setFont() is called, this is either a |
| special font for the widget class, the parent's font or (if this |
| widget is a top level widget) the default application font. |
| |
| After ensuring that the font's size is 12 points, we extract the |
| rectangles enclosing the coordinate letters, 'x' and 'y', using the |
| QFontMetrics class. |
| |
| QFontMetrics provides functions to access the individual metrics |
| of the font, its characters, and for strings rendered in the |
| font. The QFontMetrics::boundingRect() function returns the |
| bounding rectangle of the given character relative to the |
| left-most point on the base line. |
| |
| \snippet painting/transformations/renderarea.cpp 1 |
| \codeline |
| \snippet painting/transformations/renderarea.cpp 2 |
| |
| In the \c setShape() and \c setOperations() functions we update |
| the \c RenderArea widget by storing the new value or values |
| followed by a call to the QWidget::update() slot which schedules a |
| paint event for processing when Qt returns to the main event loop. |
| |
| \snippet painting/transformations/renderarea.cpp 3 |
| \codeline |
| \snippet painting/transformations/renderarea.cpp 4 |
| |
| We reimplement the QWidget's \l |
| {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l |
| {QWidget::sizeHint()}{sizeHint()} functions to give the \c |
| RenderArea widget a reasonable size within our application. The |
| default implementations of these functions returns an invalid size |
| if there is no layout for this widget, and returns the layout's |
| minimum size or preferred size, respectively, otherwise. |
| |
| \snippet painting/transformations/renderarea.cpp 5 |
| |
| The \c paintEvent() event handler receives the \c RenderArea |
| widget's paint events. A paint event is a request to repaint all |
| or part of the widget. It can happen as a result of |
| QWidget::repaint() or QWidget::update(), or because the widget was |
| obscured and has now been uncovered, or for many other reasons. |
| |
| First we create a QPainter for the \c RenderArea widget. The \l |
| {QPainter::RenderHint}{QPainter::Antialiasing} render hint |
| indicates that the engine should antialias edges of primitives if |
| possible. Then we erase the area that needs to be repainted using |
| the QPainter::fillRect() function. |
| |
| We also translate the coordinate system with an constant offset to |
| ensure that the original shape is renderend with a suitable |
| margin. |
| |
| \snippet painting/transformations/renderarea.cpp 6 |
| |
| Before we start to render the shape, we call the QPainter::save() |
| function. |
| |
| QPainter::save() saves the current painter state (i.e. pushes the |
| state onto a stack) including the current coordinate system. The |
| rationale for saving the painter state is that the following call |
| to the \c transformPainter() function will transform the |
| coordinate system depending on the currently chosen transformation |
| operations, and we need a way to get back to the original state to |
| draw the outline. |
| |
| After transforming the coordinate system, we draw the \c |
| RenderArea's shape, and then we restore the painter state using |
| the QPainter::restore() function (i.e. popping the saved state off |
| the stack). |
| |
| \snippet painting/transformations/renderarea.cpp 7 |
| |
| Then we draw the square outline. |
| |
| \snippet painting/transformations/renderarea.cpp 8 |
| |
| Since we want the coordinates to correspond with the coordinate |
| system the shape is rendered within, we must make another call to |
| the \c transformPainter() function. |
| |
| The order of the painting operations is essential with respect to |
| the shared pixels. The reason why we don't render the coordinates |
| when the coordinate system already is transformed to render the |
| shape, but instead defer their rendering to the end, is that we |
| want the coordinates to appear on top of the shape and its |
| outline. |
| |
| There is no need to save the QPainter state this time since |
| drawing the coordinates is the last painting operation. |
| |
| \snippet painting/transformations/renderarea.cpp 9 |
| \codeline |
| \snippet painting/transformations/renderarea.cpp 10 |
| \codeline |
| \snippet painting/transformations/renderarea.cpp 11 |
| |
| The \c drawCoordinates(), \c drawOutline() and \c drawShape() are |
| convenience functions called from the \c paintEvent() event |
| handler. For more information about QPainter's basic drawing |
| operations and how to display basic graphics primitives, see the |
| \l {painting/basicdrawing}{Basic Drawing} example. |
| |
| \snippet painting/transformations/renderarea.cpp 12 |
| |
| The \c transformPainter() convenience function is also called from |
| the \c paintEvent() event handler, and transforms the given |
| QPainter's coordinate system according to the user's |
| transformation choices. |
| |
| \section1 Window Class Definition |
| |
| The \c Window class is the Transformations application's main |
| window. |
| |
| The application displays four \c RenderArea widgets. The left-most |
| widget renders the shape in QPainter's default coordinate system, |
| the others render the shape with the chosen transformation in |
| addition to all the transformations applied to the \c RenderArea |
| widgets to their left. |
| |
| \snippet painting/transformations/window.h 0 |
| |
| We declare two public slots to make the application able to |
| respond to user interaction, updating the displayed \c RenderArea |
| widgets according to the user's transformation choices. |
| |
| The \c operationChanged() slot updates each of the \c RenderArea |
| widgets applying the currently chosen transformation operations, and |
| is called whenever the user changes the selected operations. The |
| \c shapeSelected() slot updates the \c RenderArea widgets' shapes |
| whenever the user changes the preferred shape. |
| |
| \snippet painting/transformations/window.h 1 |
| |
| We also declare a private convenience function, \c setupShapes(), |
| that is used when constructing the \c Window widget, and we |
| declare pointers to the various components of the widget. We |
| choose to keep the available shapes in a QList of \l |
| {QPainterPath}s. In addition we declare a private enum counting |
| the number of displayed \c RenderArea widgets except the widget |
| that renders the shape in QPainter's default coordinate system. |
| |
| \section1 Window Class Implementation |
| |
| In the constructor we create and initialize the application's |
| components: |
| |
| \snippet painting/transformations/window.cpp 0 |
| |
| First we create the \c RenderArea widget that will render the |
| shape in the default coordinate system. We also create the |
| associated QComboBox that allows the user to choose among four |
| different shapes: A clock, a house, a text and a truck. The shapes |
| themselves are created at the end of the constructor, using the |
| \c setupShapes() convenience function. |
| |
| \snippet painting/transformations/window.cpp 1 |
| |
| Then we create the \c RenderArea widgets that will render their |
| shapes with coordinate tranformations. By default the applied |
| operation is \uicontrol {No Transformation}, i.e. the shapes are |
| rendered within the default coordinate system. We create and |
| initialize the associated \l {QComboBox}es with items |
| corresponding to the various transformation operations decribed by |
| the global \c Operation enum. |
| |
| We also connect the \l {QComboBox}es' \l |
| {QComboBox::activated()}{activated()} signal to the \c |
| operationChanged() slot to update the application whenever the |
| user changes the selected transformation operations. |
| |
| \snippet painting/transformations/window.cpp 2 |
| |
| Finally, we set the layout for the application window using the |
| QWidget::setLayout() function, construct the available shapes |
| using the private \c setupShapes() convenience function, and make |
| the application show the clock shape on startup using the public |
| \c shapeSelected() slot before we set the window title. |
| |
| |
| \snippet painting/transformations/window.cpp 3 |
| \snippet painting/transformations/window.cpp 4 |
| \snippet painting/transformations/window.cpp 5 |
| \snippet painting/transformations/window.cpp 6 |
| \dots |
| |
| \snippet painting/transformations/window.cpp 7 |
| |
| The \c setupShapes() function is called from the constructor and |
| create the QPainterPath objects representing the shapes that are |
| used in the application. For construction details, see the \c |
| {painting/transformations/window.cpp} example |
| file. The shapes are stored in a QList. The QList::append() |
| function inserts the given shape at the end of the list. |
| |
| We also connect the associated QComboBox's \l |
| {QComboBox::activated()}{activated()} signal to the \c |
| shapeSelected() slot to update the application when the user |
| changes the preferred shape. |
| |
| \snippet painting/transformations/window.cpp 8 |
| |
| The public \c operationChanged() slot is called whenever the user |
| changes the selected operations. |
| |
| We retrieve the chosen transformation operation for each of the |
| transformed \c RenderArea widgets by querying the associated \l |
| {QComboBox}{QComboBoxes}. The transformed \c RenderArea widgets |
| are supposed to render the shape with the transformation specified |
| by its associated combobox \e {in addition to} all the |
| transformations applied to the \c RenderArea widgets to its |
| left. For that reason, for each widget we query, we append the |
| associated operation to a QList of transformations which we apply |
| to the widget before proceeding to the next. |
| |
| \snippet painting/transformations/window.cpp 9 |
| |
| The \c shapeSelected() slot is called whenever the user changes |
| the preferred shape, updating the \c RenderArea widgets using |
| their public \c setShape() function. |
| |
| \section1 Summary |
| |
| The Transformations example shows how transformations influence |
| the way that QPainter renders graphics primitives. Normally, the |
| QPainter operates on the device's own coordinate system, but it |
| also has good support for coordinate transformations. With the |
| Transformations application you can scale, rotate and translate |
| QPainter's coordinate system. The order in which these |
| tranformations are applied is essential for the result. |
| |
| All the tranformation operations operate on QPainter's |
| tranformation matrix. For more information about the |
| transformation matrix, see the \l {Coordinate System} and |
| QTransform documentation. |
| |
| The Qt reference documentation provides several painting |
| examples. Among these is the \l {painting/affine}{Affine |
| Transformations} example that shows Qt's ability to perform |
| transformations on painting operations. The example also allows the |
| user to experiment with the various transformation operations. |
| */ |