| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|---|
| 4 | ** All rights reserved.
|
|---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
|---|
| 6 | **
|
|---|
| 7 | ** This file is part of the documentation of the Qt Toolkit.
|
|---|
| 8 | **
|
|---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
|---|
| 10 | ** Commercial Usage
|
|---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
|---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
|---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
|---|
| 14 | ** a written agreement between you and Nokia.
|
|---|
| 15 | **
|
|---|
| 16 | ** GNU Lesser General Public License Usage
|
|---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|---|
| 18 | ** General Public License version 2.1 as published by the Free Software
|
|---|
| 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|---|
| 20 | ** packaging of this file. Please review the following information to
|
|---|
| 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|---|
| 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|---|
| 23 | **
|
|---|
| 24 | ** In addition, as a special exception, Nokia gives you certain additional
|
|---|
| 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
|---|
| 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|---|
| 27 | **
|
|---|
| 28 | ** GNU General Public License Usage
|
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 32 | ** packaging of this file. Please review the following information to
|
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
|---|
| 35 | **
|
|---|
| 36 | ** If you have questions regarding the use of this file, please contact
|
|---|
| 37 | ** Nokia at [email protected].
|
|---|
| 38 | ** $QT_END_LICENSE$
|
|---|
| 39 | **
|
|---|
| 40 | ****************************************************************************/
|
|---|
| 41 |
|
|---|
| 42 | /*!
|
|---|
| 43 | \example painting/transformations
|
|---|
| 44 | \title Transformations Example
|
|---|
| 45 |
|
|---|
| 46 | The Transformations example shows how transformations influence
|
|---|
| 47 | the way that QPainter renders graphics primitives. In particular
|
|---|
| 48 | it shows how the order of transformations affect the result.
|
|---|
| 49 |
|
|---|
| 50 | \image transformations-example.png
|
|---|
| 51 |
|
|---|
| 52 | The application allows the user to manipulate the rendering of a
|
|---|
| 53 | shape by changing the translation, rotation and scale of
|
|---|
| 54 | QPainter's coordinate system.
|
|---|
| 55 |
|
|---|
| 56 | The example consists of two classes and a global enum:
|
|---|
| 57 |
|
|---|
| 58 | \list
|
|---|
| 59 | \o The \c RenderArea class controls the rendering of a given shape.
|
|---|
| 60 | \o The \c Window class is the application's main window.
|
|---|
| 61 | \o The \c Operation enum describes the various transformation
|
|---|
| 62 | operations available in the application.
|
|---|
| 63 | \endlist
|
|---|
| 64 |
|
|---|
| 65 | First we will take a quick look at the \c Operation enum, then we
|
|---|
| 66 | will review the \c RenderArea class to see how a shape is
|
|---|
| 67 | rendered. Finally, we will take a look at the Transformations
|
|---|
| 68 | application's features implemented in the \c Window class.
|
|---|
| 69 |
|
|---|
| 70 | \section1 Transformation Operations
|
|---|
| 71 |
|
|---|
| 72 | Normally, the QPainter operates on the associated device's own
|
|---|
| 73 | coordinate system, but it also has good support for coordinate
|
|---|
| 74 | transformations.
|
|---|
| 75 |
|
|---|
| 76 | The default coordinate system of a paint device has its origin at
|
|---|
| 77 | the top-left corner. The x values increase to the right and the y
|
|---|
| 78 | values increase downwards. You can scale the coordinate system by
|
|---|
| 79 | a given offset using the QPainter::scale() function, you can
|
|---|
| 80 | rotate it clockwise using the QPainter::rotate() function and you
|
|---|
| 81 | can translate it (i.e. adding a given offset to the points) using
|
|---|
| 82 | the QPainter::translate() function. You can also twist the
|
|---|
| 83 | coordinate system around the origin (called shearing) using the
|
|---|
| 84 | QPainter::shear() function.
|
|---|
| 85 |
|
|---|
| 86 | All the tranformation operations operate on QPainter's
|
|---|
| 87 | tranformation matrix that you can retrieve using the
|
|---|
| 88 | QPainter::worldTransform() function. A matrix transforms a point in the
|
|---|
| 89 | plane to another point. For more information about the
|
|---|
| 90 | transformation matrix, see the \l {The Coordinate System} and
|
|---|
| 91 | QTransform documentation.
|
|---|
| 92 |
|
|---|
| 93 | \snippet examples/painting/transformations/renderarea.h 0
|
|---|
| 94 |
|
|---|
| 95 | The global \c Operation enum is declared in the \c renderarea.h
|
|---|
| 96 | file and describes the various transformation operations available
|
|---|
| 97 | in the Transformations application.
|
|---|
| 98 |
|
|---|
| 99 | \section1 RenderArea Class Definition
|
|---|
| 100 |
|
|---|
| 101 | The \c RenderArea class inherits QWidget, and controls the
|
|---|
| 102 | rendering of a given shape.
|
|---|
| 103 |
|
|---|
| 104 | \snippet examples/painting/transformations/renderarea.h 1
|
|---|
| 105 |
|
|---|
| 106 | We declare two public functions, \c setOperations() and
|
|---|
| 107 | \c setShape(), to be able to specify the \c RenderArea widget's shape
|
|---|
| 108 | and to transform the coordinate system the shape is rendered
|
|---|
| 109 | within.
|
|---|
| 110 |
|
|---|
| 111 | We reimplement the QWidget's \l
|
|---|
| 112 | {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
|
|---|
| 113 | {QWidget::sizeHint()}{sizeHint()} functions to give the \c
|
|---|
| 114 | RenderArea widget a reasonable size within our application, and we
|
|---|
| 115 | reimplement the QWidget::paintEvent() event handler to draw the
|
|---|
| 116 | render area's shape applying the user's transformation choices.
|
|---|
| 117 |
|
|---|
| 118 | \snippet examples/painting/transformations/renderarea.h 2
|
|---|
| 119 |
|
|---|
| 120 | We also declare several convenience functions to draw the shape,
|
|---|
| 121 | the coordinate system's outline and the coordinates, and to
|
|---|
| 122 | transform the painter according to the chosen transformations.
|
|---|
| 123 |
|
|---|
| 124 | In addition, the \c RenderArea widget keeps a list of the
|
|---|
| 125 | currently applied transformation operations, a reference to its
|
|---|
| 126 | shape, and a couple of convenience variables that we will use when
|
|---|
| 127 | rendering the coordinates.
|
|---|
| 128 |
|
|---|
| 129 | \section1 RenderArea Class Implementation
|
|---|
| 130 |
|
|---|
| 131 | The \c RenderArea widget controls the rendering of a given shape,
|
|---|
| 132 | including the transformations of the coordinate system, by
|
|---|
| 133 | reimplementing the QWidget::paintEvent() event handler. But first
|
|---|
| 134 | we will take a quick look at the constructor and at the functions
|
|---|
| 135 | that provides access to the \c RenderArea widget:
|
|---|
| 136 |
|
|---|
| 137 | \snippet examples/painting/transformations/renderarea.cpp 0
|
|---|
| 138 |
|
|---|
| 139 | In the constructor we pass the parent parameter on to the base
|
|---|
| 140 | class, and customize the font that we will use to render the
|
|---|
| 141 | coordinates. The QWidget::font() funtion returns the font
|
|---|
| 142 | currently set for the widget. As long as no special font has been
|
|---|
| 143 | set, or after QWidget::setFont() is called, this is either a
|
|---|
| 144 | special font for the widget class, the parent's font or (if this
|
|---|
| 145 | widget is a top level widget) the default application font.
|
|---|
| 146 |
|
|---|
| 147 | After ensuring that the font's size is 12 points, we extract the
|
|---|
| 148 | rectangles enclosing the coordinate letters, 'x' and 'y', using the
|
|---|
| 149 | QFontMetrics class.
|
|---|
| 150 |
|
|---|
| 151 | QFontMetrics provides functions to access the individual metrics
|
|---|
| 152 | of the font, its characters, and for strings rendered in the
|
|---|
| 153 | font. The QFontMetrics::boundingRect() function returns the
|
|---|
| 154 | bounding rectangle of the given character relative to the
|
|---|
| 155 | left-most point on the base line.
|
|---|
| 156 |
|
|---|
| 157 | \snippet examples/painting/transformations/renderarea.cpp 1
|
|---|
| 158 | \codeline
|
|---|
| 159 | \snippet examples/painting/transformations/renderarea.cpp 2
|
|---|
| 160 |
|
|---|
| 161 | In the \c setShape() and \c setOperations() functions we update
|
|---|
| 162 | the \c RenderArea widget by storing the new value or values
|
|---|
| 163 | followed by a call to the QWidget::update() slot which schedules a
|
|---|
| 164 | paint event for processing when Qt returns to the main event loop.
|
|---|
| 165 |
|
|---|
| 166 | \snippet examples/painting/transformations/renderarea.cpp 3
|
|---|
| 167 | \codeline
|
|---|
| 168 | \snippet examples/painting/transformations/renderarea.cpp 4
|
|---|
| 169 |
|
|---|
| 170 | We reimplement the QWidget's \l
|
|---|
| 171 | {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
|
|---|
| 172 | {QWidget::sizeHint()}{sizeHint()} functions to give the \c
|
|---|
| 173 | RenderArea widget a reasonable size within our application. The
|
|---|
| 174 | default implementations of these functions returns an invalid size
|
|---|
| 175 | if there is no layout for this widget, and returns the layout's
|
|---|
| 176 | minimum size or preferred size, respectively, otherwise.
|
|---|
| 177 |
|
|---|
| 178 | \snippet examples/painting/transformations/renderarea.cpp 5
|
|---|
| 179 |
|
|---|
| 180 | The \c paintEvent() event handler recieves the \c RenderArea
|
|---|
| 181 | widget's paint events. A paint event is a request to repaint all
|
|---|
| 182 | or part of the widget. It can happen as a result of
|
|---|
| 183 | QWidget::repaint() or QWidget::update(), or because the widget was
|
|---|
| 184 | obscured and has now been uncovered, or for many other reasons.
|
|---|
| 185 |
|
|---|
| 186 | First we create a QPainter for the \c RenderArea widget. The \l
|
|---|
| 187 | {QPainter::RenderHint}{QPainter::Antialiasing} render hint
|
|---|
| 188 | indicates that the engine should antialias edges of primitives if
|
|---|
| 189 | possible. Then we erase the area that needs to be repainted using
|
|---|
| 190 | the QPainter::fillRect() function.
|
|---|
| 191 |
|
|---|
| 192 | We also translate the coordinate system with an constant offset to
|
|---|
| 193 | ensure that the original shape is renderend with a suitable
|
|---|
| 194 | margin.
|
|---|
| 195 |
|
|---|
| 196 | \snippet examples/painting/transformations/renderarea.cpp 6
|
|---|
| 197 |
|
|---|
| 198 | Before we start to render the shape, we call the QPainter::save()
|
|---|
| 199 | function.
|
|---|
| 200 |
|
|---|
| 201 | QPainter::save() saves the current painter state (i.e. pushes the
|
|---|
| 202 | state onto a stack) including the current coordinate system. The
|
|---|
| 203 | rationale for saving the painter state is that the following call
|
|---|
| 204 | to the \c transformPainter() function will transform the
|
|---|
| 205 | coordinate system depending on the currently chosen transformation
|
|---|
| 206 | operations, and we need a way to get back to the original state to
|
|---|
| 207 | draw the outline.
|
|---|
| 208 |
|
|---|
| 209 | After transforming the coordinate system, we draw the \c
|
|---|
| 210 | RenderArea's shape, and then we restore the painter state using
|
|---|
| 211 | the QPainter::restore() function (i.e. popping the saved state off
|
|---|
| 212 | the stack).
|
|---|
| 213 |
|
|---|
| 214 | \snippet examples/painting/transformations/renderarea.cpp 7
|
|---|
| 215 |
|
|---|
| 216 | Then we draw the square outline.
|
|---|
| 217 |
|
|---|
| 218 | \snippet examples/painting/transformations/renderarea.cpp 8
|
|---|
| 219 |
|
|---|
| 220 | Since we want the coordinates to correspond with the coordinate
|
|---|
| 221 | system the shape is rendered within, we must make another call to
|
|---|
| 222 | the \c transformPainter() function.
|
|---|
| 223 |
|
|---|
| 224 | The order of the painting operations is essential with respect to
|
|---|
| 225 | the shared pixels. The reason why we don't render the coordinates
|
|---|
| 226 | when the coordinate system already is transformed to render the
|
|---|
| 227 | shape, but instead defer their rendering to the end, is that we
|
|---|
| 228 | want the coordinates to appear on top of the shape and its
|
|---|
| 229 | outline.
|
|---|
| 230 |
|
|---|
| 231 | There is no need to save the QPainter state this time since
|
|---|
| 232 | drawing the coordinates is the last painting operation.
|
|---|
| 233 |
|
|---|
| 234 | \snippet examples/painting/transformations/renderarea.cpp 9
|
|---|
| 235 | \codeline
|
|---|
| 236 | \snippet examples/painting/transformations/renderarea.cpp 10
|
|---|
| 237 | \codeline
|
|---|
| 238 | \snippet examples/painting/transformations/renderarea.cpp 11
|
|---|
| 239 |
|
|---|
| 240 | The \c drawCoordinates(), \c drawOutline() and \c drawShape() are
|
|---|
| 241 | convenience functions called from the \c paintEvent() event
|
|---|
| 242 | handler. For more information about QPainter's basic drawing
|
|---|
| 243 | operations and how to display basic graphics primitives, see the
|
|---|
| 244 | \l {painting/basicdrawing}{Basic Drawing} example.
|
|---|
| 245 |
|
|---|
| 246 | \snippet examples/painting/transformations/renderarea.cpp 12
|
|---|
| 247 |
|
|---|
| 248 | The \c transformPainter() convenience function is also called from
|
|---|
| 249 | the \c paintEvent() event handler, and transforms the given
|
|---|
| 250 | QPainter's coordinate system according to the user's
|
|---|
| 251 | transformation choices.
|
|---|
| 252 |
|
|---|
| 253 | \section1 Window Class Definition
|
|---|
| 254 |
|
|---|
| 255 | The \c Window class is the Transformations application's main
|
|---|
| 256 | window.
|
|---|
| 257 |
|
|---|
| 258 | The application displays four \c RenderArea widgets. The left-most
|
|---|
| 259 | widget renders the shape in QPainter's default coordinate system,
|
|---|
| 260 | the others render the shape with the chosen transformation in
|
|---|
| 261 | addition to all the transformations applied to the \c RenderArea
|
|---|
| 262 | widgets to their left.
|
|---|
| 263 |
|
|---|
| 264 | \snippet examples/painting/transformations/window.h 0
|
|---|
| 265 |
|
|---|
| 266 | We declare two public slots to make the application able to
|
|---|
| 267 | respond to user interaction, updating the displayed \c RenderArea
|
|---|
| 268 | widgets according to the user's transformation choices.
|
|---|
| 269 |
|
|---|
| 270 | The \c operationChanged() slot updates each of the \c RenderArea
|
|---|
| 271 | widgets applying the currently chosen transformation operations, and
|
|---|
| 272 | is called whenever the user changes the selected operations. The
|
|---|
| 273 | \c shapeSelected() slot updates the \c RenderArea widgets' shapes
|
|---|
| 274 | whenever the user changes the preferred shape.
|
|---|
| 275 |
|
|---|
| 276 | \snippet examples/painting/transformations/window.h 1
|
|---|
| 277 |
|
|---|
| 278 | We also declare a private convenience function, \c setupShapes(),
|
|---|
| 279 | that is used when constructing the \c Window widget, and we
|
|---|
|
|---|