1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the documentation of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file. Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
26 ****************************************************************************/
29 \example painting/transformations
30 \title Transformations Example
31 \ingroup examples-painting
32 \brief The Transformations example shows how transformations
33 influence the way that QPainter renders graphics primitives.
35 \brief The Transformations example shows how transformations influence
36 the way that QPainter renders graphics primitives. In particular
37 it shows how the order of transformations affect the result.
39 \image transformations-example.png
41 The application allows the user to manipulate the rendering of a
42 shape by changing the translation, rotation and scale of
43 QPainter's coordinate system.
45 The example consists of two classes and a global enum:
48 \li The \c RenderArea class controls the rendering of a given shape.
49 \li The \c Window class is the application's main window.
50 \li The \c Operation enum describes the various transformation
51 operations available in the application.
54 First we will take a quick look at the \c Operation enum, then we
55 will review the \c RenderArea class to see how a shape is
56 rendered. Finally, we will take a look at the Transformations
57 application's features implemented in the \c Window class.
59 \section1 Transformation Operations
61 Normally, the QPainter operates on the associated device's own
62 coordinate system, but it also has good support for coordinate
65 The default coordinate system of a paint device has its origin at
66 the top-left corner. The x values increase to the right and the y
67 values increase downwards. You can scale the coordinate system by
68 a given offset using the QPainter::scale() function, you can
69 rotate it clockwise using the QPainter::rotate() function and you
70 can translate it (i.e. adding a given offset to the points) using
71 the QPainter::translate() function. You can also twist the
72 coordinate system around the origin (called shearing) using the
73 QPainter::shear() function.
75 All the tranformation operations operate on QPainter's
76 tranformation matrix that you can retrieve using the
77 QPainter::worldTransform() function. A matrix transforms a point in the
78 plane to another point. For more information about the
79 transformation matrix, see the \l {Coordinate System} and
80 QTransform documentation.
82 \snippet painting/transformations/renderarea.h 0
84 The global \c Operation enum is declared in the \c renderarea.h
85 file and describes the various transformation operations available
86 in the Transformations application.
88 \section1 RenderArea Class Definition
90 The \c RenderArea class inherits QWidget, and controls the
91 rendering of a given shape.
93 \snippet painting/transformations/renderarea.h 1
95 We declare two public functions, \c setOperations() and
96 \c setShape(), to be able to specify the \c RenderArea widget's shape
97 and to transform the coordinate system the shape is rendered
100 We reimplement the QWidget's \l
101 {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
102 {QWidget::sizeHint()}{sizeHint()} functions to give the \c
103 RenderArea widget a reasonable size within our application, and we
104 reimplement the QWidget::paintEvent() event handler to draw the
105 render area's shape applying the user's transformation choices.
107 \snippet painting/transformations/renderarea.h 2
109 We also declare several convenience functions to draw the shape,
110 the coordinate system's outline and the coordinates, and to
111 transform the painter according to the chosen transformations.
113 In addition, the \c RenderArea widget keeps a list of the
114 currently applied transformation operations, a reference to its
115 shape, and a couple of convenience variables that we will use when
116 rendering the coordinates.
118 \section1 RenderArea Class Implementation
120 The \c RenderArea widget controls the rendering of a given shape,
121 including the transformations of the coordinate system, by
122 reimplementing the QWidget::paintEvent() event handler. But first
123 we will take a quick look at the constructor and at the functions
124 that provides access to the \c RenderArea widget:
126 \snippet painting/transformations/renderarea.cpp 0
128 In the constructor we pass the parent parameter on to the base
129 class, and customize the font that we will use to render the
130 coordinates. The QWidget::font() function returns the font
131 currently set for the widget. As long as no special font has been
132 set, or after QWidget::setFont() is called, this is either a
133 special font for the widget class, the parent's font or (if this
134 widget is a top level widget) the default application font.
136 After ensuring that the font's size is 12 points, we extract the
137 rectangles enclosing the coordinate letters, 'x' and 'y', using the
140 QFontMetrics provides functions to access the individual metrics
141 of the font, its characters, and for strings rendered in the
142 font. The QFontMetrics::boundingRect() function returns the
143 bounding rectangle of the given character relative to the
144 left-most point on the base line.
146 \snippet painting/transformations/renderarea.cpp 1
148 \snippet painting/transformations/renderarea.cpp 2
150 In the \c setShape() and \c setOperations() functions we update
151 the \c RenderArea widget by storing the new value or values
152 followed by a call to the QWidget::update() slot which schedules a
153 paint event for processing when Qt returns to the main event loop.
155 \snippet painting/transformations/renderarea.cpp 3
157 \snippet painting/transformations/renderarea.cpp 4
159 We reimplement the QWidget's \l
160 {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
161 {QWidget::sizeHint()}{sizeHint()} functions to give the \c
162 RenderArea widget a reasonable size within our application. The
163 default implementations of these functions returns an invalid size
164 if there is no layout for this widget, and returns the layout's
165 minimum size or preferred size, respectively, otherwise.
167 \snippet painting/transformations/renderarea.cpp 5
169 The \c paintEvent() event handler receives the \c RenderArea
170 widget's paint events. A paint event is a request to repaint all
171 or part of the widget. It can happen as a result of
172 QWidget::repaint() or QWidget::update(), or because the widget was
173 obscured and has now been uncovered, or for many other reasons.
175 First we create a QPainter for the \c RenderArea widget. The \l
176 {QPainter::RenderHint}{QPainter::Antialiasing} render hint
177 indicates that the engine should antialias edges of primitives if
178 possible. Then we erase the area that needs to be repainted using
179 the QPainter::fillRect() function.
181 We also translate the coordinate system with an constant offset to
182 ensure that the original shape is renderend with a suitable
185 \snippet painting/transformations/renderarea.cpp 6
187 Before we start to render the shape, we call the QPainter::save()
190 QPainter::save() saves the current painter state (i.e. pushes the
191 state onto a stack) including the current coordinate system. The
192 rationale for saving the painter state is that the following call
193 to the \c transformPainter() function will transform the
194 coordinate system depending on the currently chosen transformation
195 operations, and we need a way to get back to the original state to
198 After transforming the coordinate system, we draw the \c
199 RenderArea's shape, and then we restore the painter state using
200 the QPainter::restore() function (i.e. popping the saved state off
203 \snippet painting/transformations/renderarea.cpp 7
205 Then we draw the square outline.
207 \snippet painting/transformations/renderarea.cpp 8
209 Since we want the coordinates to correspond with the coordinate
210 system the shape is rendered within, we must make another call to
211 the \c transformPainter() function.
213 The order of the painting operations is essential with respect to
214 the shared pixels. The reason why we don't render the coordinates
215 when the coordinate system already is transformed to render the
216 shape, but instead defer their rendering to the end, is that we
217 want the coordinates to appear on top of the shape and its
220 There is no need to save the QPainter state this time since
221 drawing the coordinates is the last painting operation.
223 \snippet painting/transformations/renderarea.cpp 9
225 \snippet painting/transformations/renderarea.cpp 10
227 \snippet painting/transformations/renderarea.cpp 11
229 The \c drawCoordinates(), \c drawOutline() and \c drawShape() are
230 convenience functions called from the \c paintEvent() event
231 handler. For more information about QPainter's basic drawing
232 operations and how to display basic graphics primitives, see the
233 \l {painting/basicdrawing}{Basic Drawing} example.
235 \snippet painting/transformations/renderarea.cpp 12
237 The \c transformPainter() convenience function is also called from
238 the \c paintEvent() event handler, and transforms the given
239 QPainter's coordinate system according to the user's
240 transformation choices.
242 \section1 Window Class Definition
244 The \c Window class is the Transformations application's main
247 The application displays four \c RenderArea widgets. The left-most
248 widget renders the shape in QPainter's default coordinate system,
249 the others render the shape with the chosen transformation in
250 addition to all the transformations applied to the \c RenderArea
251 widgets to their left.
253 \snippet painting/transformations/window.h 0
255 We declare two public slots to make the application able to
256 respond to user interaction, updating the displayed \c RenderArea
257 widgets according to the user's transformation choices.
259 The \c operationChanged() slot updates each of the \c RenderArea
260 widgets applying the currently chosen transformation operations, and
261 is called whenever the user changes the selected operations. The
262 \c shapeSelected() slot updates the \c RenderArea widgets' shapes
263 whenever the user changes the preferred shape.
265 \snippet painting/transformations/window.h 1
267 We also declare a private convenience function, \c setupShapes(),
268 that is used when constructing the \c Window widget, and we
269 declare pointers to the various components of the widget. We
270 choose to keep the available shapes in a QList of \l
271 {QPainterPath}s. In addition we declare a private enum counting
272 the number of displayed \c RenderArea widgets except the widget
273 that renders the shape in QPainter's default coordinate system.
275 \section1 Window Class Implementation
277 In the constructor we create and initialize the application's
280 \snippet painting/transformations/window.cpp 0
282 First we create the \c RenderArea widget that will render the
283 shape in the default coordinate system. We also create the
284 associated QComboBox that allows the user to choose among four
285 different shapes: A clock, a house, a text and a truck. The shapes
286 themselves are created at the end of the constructor, using the
287 \c setupShapes() convenience function.
289 \snippet painting/transformations/window.cpp 1
291 Then we create the \c RenderArea widgets that will render their
292 shapes with coordinate tranformations. By default the applied
293 operation is \uicontrol {No Transformation}, i.e. the shapes are
294 rendered within the default coordinate system. We create and
295 initialize the associated \l {QComboBox}es with items
296 corresponding to the various transformation operations decribed by
297 the global \c Operation enum.
299 We also connect the \l {QComboBox}es' \l
300 {QComboBox::activated()}{activated()} signal to the \c
301 operationChanged() slot to update the application whenever the
302 user changes the selected transformation operations.
304 \snippet painting/transformations/window.cpp 2
306 Finally, we set the layout for the application window using the
307 QWidget::setLayout() function, construct the available shapes
308 using the private \c setupShapes() convenience function, and make
309 the application show the clock shape on startup using the public
310 \c shapeSelected() slot before we set the window title.
313 \snippet painting/transformations/window.cpp 3
314 \snippet painting/transformations/window.cpp 4
315 \snippet painting/transformations/window.cpp 5
316 \snippet painting/transformations/window.cpp 6
319 \snippet painting/transformations/window.cpp 7
321 The \c setupShapes() function is called from the constructor and
322 create the QPainterPath objects representing the shapes that are
323 used in the application. For construction details, see the \l
324 {painting/transformations/window.cpp}{window.cpp} example
325 file. The shapes are stored in a QList. The QList::append()
326 function inserts the given shape at the end of the list.
328 We also connect the associated QComboBox's \l
329 {QComboBox::activated()}{activated()} signal to the \c
330 shapeSelected() slot to update the application when the user
331 changes the preferred shape.
333 \snippet painting/transformations/window.cpp 8
335 The public \c operationChanged() slot is called whenever the user
336 changes the selected operations.
338 We retrieve the chosen transformation operation for each of the
339 transformed \c RenderArea widgets by querying the associated \l
340 {QComboBox}{QComboBoxes}. The transformed \c RenderArea widgets
341 are supposed to render the shape with the transformation specified
342 by its associated combobox \e {in addition to} all the
343 transformations applied to the \c RenderArea widgets to its
344 left. For that reason, for each widget we query, we append the
345 associated operation to a QList of transformations which we apply
346 to the widget before proceeding to the next.
348 \snippet painting/transformations/window.cpp 9
350 The \c shapeSelected() slot is called whenever the user changes
351 the preferred shape, updating the \c RenderArea widgets using
352 their public \c setShape() function.
356 The Transformations example shows how transformations influence
357 the way that QPainter renders graphics primitives. Normally, the
358 QPainter operates on the device's own coordinate system, but it
359 also has good support for coordinate transformations. With the
360 Transformations application you can scale, rotate and translate
361 QPainter's coordinate system. The order in which these
362 tranformations are applied is essential for the result.
364 All the tranformation operations operate on QPainter's
365 tranformation matrix. For more information about the
366 transformation matrix, see the \l {Coordinate System} and
367 QTransform documentation.
369 The Qt reference documentation provides several painting
370 examples. Among these is the \l {painting/affine}{Affine
371 Transformations} example that shows Qt's ability to perform
372 transformations on painting operations. The example also allows the
373 user to experiment with the various transformation operations.