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

Last change on this file since 560 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 17.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the documentation of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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::matrix() 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 QMatrix 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 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
280 declare pointers to the various components of the widget. We
281 choose to keep the available shapes in a QList of \l
282 {QPainterPath}s. In addition we declare a private enum counting
283 the number of displayed \c RenderArea widgets except the widget
284 that renders the shape in QPainter's default coordinate system.
285
286 \section1 Window Class Implementation
287
288 In the constructor we create and initialize the application's
289 components:
290
291 \snippet examples/painting/transformations/window.cpp 0
292
293 First we create the \c RenderArea widget that will render the
294 shape in the default coordinate system. We also create the
295 associated QComboBox that allows the user to choose among four
296 different shapes: A clock, a house, a text and a truck. The shapes
297 themselves are created at the end of the constructor, using the
298 \c setupShapes() convenience function.
299
300 \snippet examples/painting/transformations/window.cpp 1
301
302 Then we create the \c RenderArea widgets that will render their
303 shapes with coordinate tranformations. By default the applied
304 operation is \gui {No Transformation}, i.e. the shapes are
305 rendered within the default coordinate system. We create and
306 initialize the associated \l {QComboBox}es with items
307 corresponding to the various transformation operations decribed by
308 the global \c Operation enum.
309
310 We also connect the \l {QComboBox}es' \l
311 {QComboBox::activated()}{activated()} signal to the \c
312 operationChanged() slot to update the application whenever the
313 user changes the selected transformation operations.
314
315 \snippet examples/painting/transformations/window.cpp 2
316
317 Finally, we set the layout for the application window using the
318 QWidget::setLayout() function, construct the available shapes
319 using the private \c setupShapes() convenience function, and make
320 the application show the clock shape on startup using the public
321 \c shapeSelected() slot before we set the window title.
322
323
324 \snippet examples/painting/transformations/window.cpp 3
325 \snippet examples/painting/transformations/window.cpp 4
326 \snippet examples/painting/transformations/window.cpp 5
327 \snippet examples/painting/transformations/window.cpp 6
328 \dots
329
330 \snippet examples/painting/transformations/window.cpp 7
331
332 The \c setupShapes() function is called from the constructor and
333 create the QPainterPath objects representing the shapes that are
334 used in the application. For construction details, see the \l
335 {painting/transformations/window.cpp}{window.cpp} example
336 file. The shapes are stored in a QList. The QList::append()
337 function inserts the given shape at the end of the list.
338
339 We also connect the associated QComboBox's \l
340 {QComboBox::activated()}{activated()} signal to the \c
341 shapeSelected() slot to update the application when the user
342 changes the preferred shape.
343
344 \snippet examples/painting/transformations/window.cpp 8
345
346 The public \c operationChanged() slot is called whenever the user
347 changes the selected operations.
348
349 We retrieve the chosen transformation operation for each of the
350 transformed \c RenderArea widgets by querying the associated \l
351 {QComboBox}{QComboBoxes}. The transformed \c RenderArea widgets
352 are supposed to render the shape with the transformation specified
353 by its associated combobox \e {in addition to} all the
354 transformations applied to the \c RenderArea widgets to its
355 left. For that reason, for each widget we query, we append the
356 associated operation to a QList of transformations which we apply
357 to the widget before proceeding to the next.
358
359 \snippet examples/painting/transformations/window.cpp 9
360
361 The \c shapeSelected() slot is called whenever the user changes
362 the preferred shape, updating the \c RenderArea widgets using
363 their public \c setShape() function.
364
365 \section1 Summary
366
367 The Transformations example shows how transformations influence
368 the way that QPainter renders graphics primitives. Normally, the
369 QPainter operates on the device's own coordinate system, but it
370 also has good support for coordinate transformations. With the
371 Transformations application you can scale, rotate and translate
372 QPainter's coordinate system. The order in which these
373 tranformations are applied is essential for the result.
374
375 All the tranformation operations operate on QPainter's
376 tranformation matrix. For more information about the
377 transformation matrix, see the \l {The Coordinate System} and
378 QMatrix documentation.
379
380 The Qt reference documentation provides several painting
381 demos. Among these is the \l {demos/affine}{Affine
382 Transformations} demo that shows Qt's ability to perform
383 transformations on painting operations. The demo also allows the
384 user to experiment with the various transformation operations.
385*/
Note: See TracBrowser for help on using the repository browser.