doc/src/examples/tablet.qdoc
branchRCL_3
changeset 8 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 8:3f74d0d4af4c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 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     generated. 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            offscreen pixmap, 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 QPixmap with \c myPen and \c myBrush using \c
       
   218     myColor. The \c saveImage() and \c loadImage() saves and loads
       
   219     the QPixmap to disk. The pixmap 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 paintPixmap(), \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 pixmap, 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     QPixmap implements functionality to save itself to disk, so we
       
   244     simply call \l{QPixmap::}{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{QPixmap::}{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 paintPixmap() 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 pixmap to the top left of the widget.
       
   271 
       
   272     Here is the implementation of \c paintPixmap():
       
   273 
       
   274     \snippet examples/widgets/tablet/tabletcanvas.cpp 5
       
   275 
       
   276     In this function we draw on the pixmap 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. We
       
   279     also assume that this is a reasonable handling of any unknown device,
       
   280     but update the statusbar with a warning so that the user can see that
       
   281     for his tablet he might have to implement special handling.
       
   282     If it is an airbrush we want to draw a circle of points with a
       
   283     point density based on the tangential pressure, which is the position
       
   284     of the finger wheel on the airbrush. We use the Qt::BrushStyle to
       
   285     draw the points as it has styles that draw points with different
       
   286     density; we select the style based on the tangential pressure in
       
   287     \c brushPattern().
       
   288 
       
   289     \snippet examples/widgets/tablet/tabletcanvas.cpp 6
       
   290 
       
   291     We return a brush style with a point density that increases with
       
   292     the tangential pressure.
       
   293 
       
   294     In \c updateBrush() we set the pen and brush used for drawing
       
   295     to match \c alphaChannelType, \c lineWidthType, \c
       
   296     colorSaturationType, and \c myColor. We will examine the code to
       
   297     set up \c myBrush and \c myPen for each of these variables:
       
   298 
       
   299     \snippet examples/widgets/tablet/tabletcanvas.cpp 7
       
   300 
       
   301     We fetch the current drawingcolor's hue, saturation, value,
       
   302     and alpha values. \c hValue and \c vValue are set to the
       
   303     horizontal and vertical tilt as a number from 0 to 255. The
       
   304     original values are in degrees from -60 to 60, i.e., 0 equals
       
   305     -60, 127 equals 0, and 255 equals 60 degrees. The angle measured
       
   306     is between the device and the perpendicular of the tablet (see
       
   307     QTabletEvent for an illustration).
       
   308          
       
   309     \snippet examples/widgets/tablet/tabletcanvas.cpp 8
       
   310 
       
   311     The alpha channel of QColor is given as a number between 0
       
   312     and 255 where 0 is transparent and 255 is opaque.
       
   313     \l{QTabletEvent::}{pressure()} returns the pressure as a qreal
       
   314     between 0.0 and 1.0. By subtracting 127 from the tilt values and
       
   315     taking the absolute value we get the smallest alpha values (i.e.,
       
   316     the color is most transparent) when the pen is perpendicular to
       
   317     the tablet. We select the largest of the vertical and horizontal
       
   318     tilt value. 
       
   319  
       
   320     \snippet examples/widgets/tablet/tabletcanvas.cpp 9
       
   321 
       
   322     The colorsaturation is given as a number between 0 and 255. It is
       
   323     set with \l{QColor::}{setHsv()}. We can set the tilt values
       
   324     directly, but must multiply the pressure to a number between 0 and
       
   325     255.
       
   326 
       
   327     \snippet examples/widgets/tablet/tabletcanvas.cpp 10
       
   328 
       
   329     The width of the pen increases with the pressure. When the pen
       
   330     width is controlled with the tilt we let the width increse with
       
   331     the angle between the device and the perpendicular of the tablet.
       
   332 
       
   333     \snippet examples/widgets/tablet/tabletcanvas.cpp 11
       
   334    
       
   335     We finally check wether the pointer is the stylus or the eraser.
       
   336     If it is the eraser, we set the color to the background color of
       
   337     the pixmap an let the pressure decide the pen width, else we set
       
   338     the colors we have set up previously in the function.
       
   339 
       
   340 
       
   341     \section1 TabletApplication Class Definition
       
   342 
       
   343     We inherit QApplication in this class because we want to
       
   344     reimplement the \l{QApplication::}{event()} function. 
       
   345 
       
   346     \snippet examples/widgets/tablet/tabletapplication.h 0
       
   347 
       
   348     We keep a \c TabletCanvas we send the device type of the events we
       
   349     handle in the \c event() function to. The TabletEnterProximity
       
   350     and TabletLeaveProximity events are not sendt to the QApplication
       
   351     object, while other tablet events are sendt to the QWidget's
       
   352     \c event(), which sends them on to \l{QWidget::}{tabletEvent()}.
       
   353     Since we want to handle these events we have implemented \c 
       
   354     TabletApplication.
       
   355 
       
   356 
       
   357     \section1 TabletApplication Class Implementation
       
   358 
       
   359     Here is the implementation of \c event():
       
   360 
       
   361     \snippet examples/widgets/tablet/tabletapplication.cpp 0
       
   362 
       
   363     We use this function to handle the TabletEnterProximity and
       
   364     TabletLeaveProximity events, which is generated when a device
       
   365     enters and leaves the proximity of the tablet. The intended use of these
       
   366     events is to do work that is dependent on what kind of device is
       
   367     used on the tablet. This way, you don't have to do this work
       
   368     when other events are generated, which is more frequently than the
       
   369     leave and enter proximity events. We call \c setTabletDevice() in 
       
   370     \c TabletCanvas.
       
   371 
       
   372     \section1 The \c main() function
       
   373 
       
   374     Here is the examples \c main() function:
       
   375 
       
   376     \snippet examples/widgets/tablet/main.cpp 0
       
   377 
       
   378     In the \c main() function we create a \c MainWinow and display it
       
   379     as a top level window. We use the \c TabletApplication class. We
       
   380     need to set the canvas after the application is created. We cannot
       
   381     use classes that implement event handling before an QApplication
       
   382     object is instantiated.
       
   383 */