source: trunk/doc/src/examples/tablet.qdoc@ 846

Last change on this file since 846 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: 14.6 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 widgets/tablet
30 \title Tablet Example
31
32 This example shows how to use a Wacom tablet in Qt applications.
33
34 \image tabletexample.png
35
36 When you use a tablet with Qt applications, \l{QTabletEvent}s are
37 generated. You need to reimplement the
38 \l{QWidget::}{tabletEvent()} event handler if you want to handle
39 tablet events. Events are generated when the device used for
40 drawing enters and leaves the proximity of the tablet (i.e., when
41 it is close but not pressed down on it), when a device is pushed
42 down and released from it, and when a device is moved on the
43 tablet.
44
45 The information available in QTabletEvent depends on the device
46 used. The tablet in this example has two different devices for
47 drawing: a stylus and an airbrush. For both devices the event
48 contains the position of the device, pressure on the tablet,
49 vertical tilt, and horizontal tilt (i.e, the angle between the
50 device and the perpendicular of the tablet). The airbrush has a
51 finger wheel; the position of this is also available in the tablet
52 event.
53
54 In this example we implement a drawing program. You can use the
55 stylus to draw on the tablet as you use a pencil on paper. When
56 you draw with the airbrush you get a spray of paint; the finger
57 wheel is used to change the density of the spray. The pressure and
58 tilt can change the alpha and saturation values of the QColor and the
59 width of the QPen used for drawing.
60
61 The example consists of the following:
62
63 \list
64 \o The \c MainWindow class inherits QMainWindow and creates
65 the examples menus and connect their slots and signals.
66 \o The \c TabletCanvas class inherits QWidget and
67 receives tablet events. It uses the events to paint on a
68 offscreen pixmap, which it draws onto itself.
69 \o The \c TabletApplication class inherits QApplication. This
70 class handles tablet events that are not sent to \c tabletEvent().
71 We will look at this later.
72 \o The \c main() function creates a \c MainWindow and shows it
73 as a top level window.
74 \endlist
75
76
77 \section1 MainWindow Class Definition
78
79 The \c MainWindow creates a \c TabletCanvas and sets it as its
80 center widget.
81
82 \snippet examples/widgets/tablet/mainwindow.h 0
83
84 The QActions let the user select if the tablets pressure and
85 tilt should change the pen width, color alpha component and color
86 saturation. \c createActions() creates all actions, and \c
87 createMenus() sets up the menus with the actions. We have one
88 QActionGroup for the actions that alter the alpha channel, color
89 saturation and line width respectively. The action groups are
90 connected to the \c alphaActionTriggered(), \c
91 colorSaturationActiontriggered(), and \c
92 lineWidthActionTriggered() slots, which calls functions in \c
93 myCanvas.
94
95
96 \section1 MainWindow Class Implementation
97
98 We start width a look at the constructor \c MainWindow():
99
100 \snippet examples/widgets/tablet/mainwindow.cpp 0
101
102 In the constructor we create the canvas, actions, and menus.
103 We set the canvas as the center widget. We also initialize the
104 canvas to match the state of our menus and start drawing with a
105 red color.
106
107 Here is the implementation of \c brushColorAct():
108
109 \snippet examples/widgets/tablet/mainwindow.cpp 1
110
111 We let the user pick a color with a QColorDialog. If it is valid,
112 we set a new drawing color with \c setColor().
113
114 Here is the implementation of \c alphaActionTriggered():
115
116 \snippet examples/widgets/tablet/mainwindow.cpp 2
117
118 The \c TabletCanvas class supports two ways by which the alpha
119 channel of the drawing color can be changed: tablet pressure and
120 tilt. We have one action for each and an action if the alpha
121 channel should not be changed.
122
123 Here is the implementation of \c lineWidthActionTriggered():
124
125 \snippet examples/widgets/tablet/mainwindow.cpp 3
126
127 We check which action is selected in \c lineWidthGroup, and set
128 how the canvas should change the drawing line width.
129
130 Here is the implementation of \c saturationActionTriggered():
131
132 \snippet examples/widgets/tablet/mainwindow.cpp 4
133
134 We check which action is selected in \c colorSaturationGroup, and
135 set how the canvas should change the color saturation of the
136 drawing color.
137
138 Here is the implementation of \c saveAct():
139
140 \snippet examples/widgets/tablet/mainwindow.cpp 5
141
142 We use the QFileDialog to let the user select a file to save the
143 drawing in. It is the \c TabletCanvas that save the drawing, so we
144 call its \c saveImage() function.
145
146 Here is the implementation of \c loadAct():
147
148 \snippet examples/widgets/tablet/mainwindow.cpp 6
149
150 We let the user select the image file to be opened with
151 a QFileDialog; we then ask the canvas to load the image with \c
152 loadImage().
153
154 Here is the implementation of \c aboutAct():
155
156 \snippet examples/widgets/tablet/mainwindow.cpp 7
157
158 We show a message box with a short description of the example.
159
160 \c createActions() creates all actions and action groups of
161 the example. We look at the creation of one action group and its
162 actions. See the \l{Application Example}{application example} if
163 you want a high-level introduction to QActions.
164
165 Here is the implementation of \c createActions:
166
167 \snippet examples/widgets/tablet/mainwindow.cpp 8
168 \dots
169 \snippet examples/widgets/tablet/mainwindow.cpp 9
170
171 We want the user to be able to choose if the drawing color's
172 alpha component should be changed by the tablet pressure or tilt.
173 We have one action for each choice and an action if the alpha
174 channel is not to be changed, i.e, the color is opaque. We make
175 the actions checkable; the \c alphaChannelGroup will then ensure
176 that only one of the actions are checked at any time. The \c
177 triggered() signal is emitted when an action is checked.
178
179 \dots
180 \snippet examples/widgets/tablet/mainwindow.cpp 10
181
182 Here is the implementation of \c createMenus():
183
184 \snippet examples/widgets/tablet/mainwindow.cpp 11
185
186 We create the menus of the example and add the actions to them.
187
188
189 \section1 TabletCanvas Class Definition
190
191 The \c TabletCanvas class provides a surface on which the
192 user can draw with a tablet.
193
194 \snippet examples/widgets/tablet/tabletcanvas.h 0
195
196 The canvas can change the alpha channel, color saturation,
197 and line width of the drawing. We have one enum for each of
198 these; their values decide if it is the tablet pressure or tilt
199 that will alter them. We keep a private variable for each, the \c
200 alphaChannelType, \c colorSturationType, and \c penWidthType,
201 which we provide access functions for.
202
203 We draw on a QPixmap with \c myPen and \c myBrush using \c
204 myColor. The \c saveImage() and \c loadImage() saves and loads
205 the QPixmap to disk. The pixmap is drawn on the widget in \c
206 paintEvent(). The \c pointerType and \c deviceType keeps the type
207 of pointer, which is either a pen or an eraser, and device
208 currently used on the tablet, which is either a stylus or an
209 airbrush.
210
211 The interpretation of events from the tablet is done in \c
212 tabletEvent(); \c paintPixmap(), \c updateBrush(), and \c
213 brushPattern() are helper functions used by \c tabletEvent().
214
215
216 \section1 TabletCanvas Class Implementation
217
218 We start with a look at the constructor:
219
220 \snippet examples/widgets/tablet/tabletcanvas.cpp 0
221
222 In the constructor we initialize our class variables. We need
223 to draw the background of our pixmap, as the default is gray.
224
225 Here is the implementation of \c saveImage():
226
227 \snippet examples/widgets/tablet/tabletcanvas.cpp 1
228
229 QPixmap implements functionality to save itself to disk, so we
230 simply call \l{QPixmap::}{save()}.
231
232 Here is the implementation of \c loadImage():
233
234 \snippet examples/widgets/tablet/tabletcanvas.cpp 2
235
236 We simply call \l{QPixmap::}{load()}, which loads the image in \a
237 file.
238
239 Here is the implementation of \c tabletEvent():
240
241 \snippet examples/widgets/tablet/tabletcanvas.cpp 3
242
243 We get three kind of events to this function: TabletPress,
244 TabletRelease, and TabletMove, which is generated when a device
245 is pressed down on, leaves, or moves on the tablet. We set the \c
246 deviceDown to true when a device is pressed down on the tablet;
247 we then know when we should draw when we receive move events. We
248 have implemented the \c updateBrush() and \c paintPixmap() helper
249 functions to update \c myBrush and \c myPen after the state of \c
250 alphaChannelType, \c colorSaturationType, and \c lineWidthType.
251
252 Here is the implementation of \c paintEvent():
253
254 \snippet examples/widgets/tablet/tabletcanvas.cpp 4
255
256 We simply draw the pixmap to the top left of the widget.
257
258 Here is the implementation of \c paintPixmap():
259
260 \snippet examples/widgets/tablet/tabletcanvas.cpp 5
261
262 In this function we draw on the pixmap based on the movement of the
263 device. If the device used on the tablet is a stylus we want to draw a
264 line between the positions of the stylus recorded in \c polyLine. We
265 also assume that this is a reasonable handling of any unknown device,
266 but update the statusbar with a warning so that the user can see that
267 for his tablet he might have to implement special handling.
268 If it is an airbrush we want to draw a circle of points with a
269 point density based on the tangential pressure, which is the position
270 of the finger wheel on the airbrush. We use the Qt::BrushStyle to
271 draw the points as it has styles that draw points with different
272 density; we select the style based on the tangential pressure in
273 \c brushPattern().
274
275 \snippet examples/widgets/tablet/tabletcanvas.cpp 6
276
277 We return a brush style with a point density that increases with
278 the tangential pressure.
279
280 In \c updateBrush() we set the pen and brush used for drawing
281 to match \c alphaChannelType, \c lineWidthType, \c
282 colorSaturationType, and \c myColor. We will examine the code to
283 set up \c myBrush and \c myPen for each of these variables:
284
285 \snippet examples/widgets/tablet/tabletcanvas.cpp 7
286
287 We fetch the current drawingcolor's hue, saturation, value,
288 and alpha values. \c hValue and \c vValue are set to the
289 horizontal and vertical tilt as a number from 0 to 255. The
290 original values are in degrees from -60 to 60, i.e., 0 equals
291 -60, 127 equals 0, and 255 equals 60 degrees. The angle measured
292 is between the device and the perpendicular of the tablet (see
293 QTabletEvent for an illustration).
294
295 \snippet examples/widgets/tablet/tabletcanvas.cpp 8
296
297 The alpha channel of QColor is given as a number between 0
298 and 255 where 0 is transparent and 255 is opaque.
299 \l{QTabletEvent::}{pressure()} returns the pressure as a qreal
300 between 0.0 and 1.0. By subtracting 127 from the tilt values and
301 taking the absolute value we get the smallest alpha values (i.e.,
302 the color is most transparent) when the pen is perpendicular to
303 the tablet. We select the largest of the vertical and horizontal
304 tilt value.
305
306 \snippet examples/widgets/tablet/tabletcanvas.cpp 9
307
308 The colorsaturation is given as a number between 0 and 255. It is
309 set with \l{QColor::}{setHsv()}. We can set the tilt values
310 directly, but must multiply the pressure to a number between 0 and
311 255.
312
313 \snippet examples/widgets/tablet/tabletcanvas.cpp 10
314
315 The width of the pen increases with the pressure. When the pen
316 width is controlled with the tilt we let the width increse with
317 the angle between the device and the perpendicular of the tablet.
318
319 \snippet examples/widgets/tablet/tabletcanvas.cpp 11
320
321 We finally check wether the pointer is the stylus or the eraser.
322 If it is the eraser, we set the color to the background color of
323 the pixmap an let the pressure decide the pen width, else we set
324 the colors we have set up previously in the function.
325
326
327 \section1 TabletApplication Class Definition
328
329 We inherit QApplication in this class because we want to
330 reimplement the \l{QApplication::}{event()} function.
331
332 \snippet examples/widgets/tablet/tabletapplication.h 0
333
334 We keep a \c TabletCanvas we send the device type of the events we
335 handle in the \c event() function to. The TabletEnterProximity
336 and TabletLeaveProximity events are not sendt to the QApplication
337 object, while other tablet events are sendt to the QWidget's
338 \c event(), which sends them on to \l{QWidget::}{tabletEvent()}.
339 Since we want to handle these events we have implemented \c
340 TabletApplication.
341
342
343 \section1 TabletApplication Class Implementation
344
345 Here is the implementation of \c event():
346
347 \snippet examples/widgets/tablet/tabletapplication.cpp 0
348
349 We use this function to handle the TabletEnterProximity and
350 TabletLeaveProximity events, which is generated when a device
351 enters and leaves the proximity of the tablet. The intended use of these
352 events is to do work that is dependent on what kind of device is
353 used on the tablet. This way, you don't have to do this work
354 when other events are generated, which is more frequently than the
355 leave and enter proximity events. We call \c setTabletDevice() in
356 \c TabletCanvas.
357
358 \section1 The \c main() function
359
360 Here is the examples \c main() function:
361
362 \snippet examples/widgets/tablet/main.cpp 0
363
364 In the \c main() function we create a \c MainWinow and display it
365 as a top level window. We use the \c TabletApplication class. We
366 need to set the canvas after the application is created. We cannot
367 use classes that implement event handling before an QApplication
368 object is instantiated.
369*/
Note: See TracBrowser for help on using the repository browser.