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

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

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

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