|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 |
|
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 QTransform 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 */ |