source: trunk/doc/src/examples/transformations.qdoc

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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