Update copyright headers
[qt:qt.git] / doc / src / examples / tablet.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file.  Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \example widgets/tablet
30     \title Tablet Example
31
32     \brief The Tablet 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 */