diff -r dee5afe5301f -r 3f74d0d4af4c doc/src/examples/tablet.qdoc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/src/examples/tablet.qdoc Thu Apr 08 14:19:33 2010 +0300 @@ -0,0 +1,383 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example widgets/tablet + \title Tablet Example + + This example shows how to use a Wacom tablet in Qt applications. + + \image tabletexample.png + + When you use a tablet with Qt applications, \l{QTabletEvent}s are + generated. You need to reimplement the + \l{QWidget::}{tabletEvent()} event handler if you want to handle + tablet events. Events are generated when the device used for + drawing enters and leaves the proximity of the tablet (i.e., when + it is close but not pressed down on it), when a device is pushed + down and released from it, and when a device is moved on the + tablet. + + The information available in QTabletEvent depends on the device + used. The tablet in this example has two different devices for + drawing: a stylus and an airbrush. For both devices the event + contains the position of the device, pressure on the tablet, + vertical tilt, and horizontal tilt (i.e, the angle between the + device and the perpendicular of the tablet). The airbrush has a + finger wheel; the position of this is also available in the tablet + event. + + In this example we implement a drawing program. You can use the + stylus to draw on the tablet as you use a pencil on paper. When + you draw with the airbrush you get a spray of paint; the finger + wheel is used to change the density of the spray. The pressure and + tilt can change the alpha and saturation values of the QColor and the + width of the QPen used for drawing. + + The example consists of the following: + + \list + \o The \c MainWindow class inherits QMainWindow and creates + the examples menus and connect their slots and signals. + \o The \c TabletCanvas class inherits QWidget and + receives tablet events. It uses the events to paint on a + offscreen pixmap, which it draws onto itself. + \o The \c TabletApplication class inherits QApplication. This + class handles tablet events that are not sent to \c tabletEvent(). + We will look at this later. + \o The \c main() function creates a \c MainWindow and shows it + as a top level window. + \endlist + + + \section1 MainWindow Class Definition + + The \c MainWindow creates a \c TabletCanvas and sets it as its + center widget. + + \snippet examples/widgets/tablet/mainwindow.h 0 + + The QActions let the user select if the tablets pressure and + tilt should change the pen width, color alpha component and color + saturation. \c createActions() creates all actions, and \c + createMenus() sets up the menus with the actions. We have one + QActionGroup for the actions that alter the alpha channel, color + saturation and line width respectively. The action groups are + connected to the \c alphaActionTriggered(), \c + colorSaturationActiontriggered(), and \c + lineWidthActionTriggered() slots, which calls functions in \c + myCanvas. + + + \section1 MainWindow Class Implementation + + We start width a look at the constructor \c MainWindow(): + + \snippet examples/widgets/tablet/mainwindow.cpp 0 + + In the constructor we create the canvas, actions, and menus. + We set the canvas as the center widget. We also initialize the + canvas to match the state of our menus and start drawing with a + red color. + + Here is the implementation of \c brushColorAct(): + + \snippet examples/widgets/tablet/mainwindow.cpp 1 + + We let the user pick a color with a QColorDialog. If it is valid, + we set a new drawing color with \c setColor(). + + Here is the implementation of \c alphaActionTriggered(): + + \snippet examples/widgets/tablet/mainwindow.cpp 2 + + The \c TabletCanvas class supports two ways by which the alpha + channel of the drawing color can be changed: tablet pressure and + tilt. We have one action for each and an action if the alpha + channel should not be changed. + + Here is the implementation of \c lineWidthActionTriggered(): + + \snippet examples/widgets/tablet/mainwindow.cpp 3 + + We check which action is selected in \c lineWidthGroup, and set + how the canvas should change the drawing line width. + + Here is the implementation of \c saturationActionTriggered(): + + \snippet examples/widgets/tablet/mainwindow.cpp 4 + + We check which action is selected in \c colorSaturationGroup, and + set how the canvas should change the color saturation of the + drawing color. + + Here is the implementation of \c saveAct(): + + \snippet examples/widgets/tablet/mainwindow.cpp 5 + + We use the QFileDialog to let the user select a file to save the + drawing in. It is the \c TabletCanvas that save the drawing, so we + call its \c saveImage() function. + + Here is the implementation of \c loadAct(): + + \snippet examples/widgets/tablet/mainwindow.cpp 6 + + We let the user select the image file to be opened with + a QFileDialog; we then ask the canvas to load the image with \c + loadImage(). + + Here is the implementation of \c aboutAct(): + + \snippet examples/widgets/tablet/mainwindow.cpp 7 + + We show a message box with a short description of the example. + + \c createActions() creates all actions and action groups of + the example. We look at the creation of one action group and its + actions. See the \l{Application Example}{application example} if + you want a high-level introduction to QActions. + + Here is the implementation of \c createActions: + + \snippet examples/widgets/tablet/mainwindow.cpp 8 + \dots + \snippet examples/widgets/tablet/mainwindow.cpp 9 + + We want the user to be able to choose if the drawing color's + alpha component should be changed by the tablet pressure or tilt. + We have one action for each choice and an action if the alpha + channel is not to be changed, i.e, the color is opaque. We make + the actions checkable; the \c alphaChannelGroup will then ensure + that only one of the actions are checked at any time. The \c + triggered() signal is emitted when an action is checked. + + \dots + \snippet examples/widgets/tablet/mainwindow.cpp 10 + + Here is the implementation of \c createMenus(): + + \snippet examples/widgets/tablet/mainwindow.cpp 11 + + We create the menus of the example and add the actions to them. + + + \section1 TabletCanvas Class Definition + + The \c TabletCanvas class provides a surface on which the + user can draw with a tablet. + + \snippet examples/widgets/tablet/tabletcanvas.h 0 + + The canvas can change the alpha channel, color saturation, + and line width of the drawing. We have one enum for each of + these; their values decide if it is the tablet pressure or tilt + that will alter them. We keep a private variable for each, the \c + alphaChannelType, \c colorSturationType, and \c penWidthType, + which we provide access functions for. + + We draw on a QPixmap with \c myPen and \c myBrush using \c + myColor. The \c saveImage() and \c loadImage() saves and loads + the QPixmap to disk. The pixmap is drawn on the widget in \c + paintEvent(). The \c pointerType and \c deviceType keeps the type + of pointer, which is either a pen or an eraser, and device + currently used on the tablet, which is either a stylus or an + airbrush. + + The interpretation of events from the tablet is done in \c + tabletEvent(); \c paintPixmap(), \c updateBrush(), and \c + brushPattern() are helper functions used by \c tabletEvent(). + + + \section1 TabletCanvas Class Implementation + + We start with a look at the constructor: + + \snippet examples/widgets/tablet/tabletcanvas.cpp 0 + + In the constructor we initialize our class variables. We need + to draw the background of our pixmap, as the default is gray. + + Here is the implementation of \c saveImage(): + + \snippet examples/widgets/tablet/tabletcanvas.cpp 1 + + QPixmap implements functionality to save itself to disk, so we + simply call \l{QPixmap::}{save()}. + + Here is the implementation of \c loadImage(): + + \snippet examples/widgets/tablet/tabletcanvas.cpp 2 + + We simply call \l{QPixmap::}{load()}, which loads the image in \a + file. + + Here is the implementation of \c tabletEvent(): + + \snippet examples/widgets/tablet/tabletcanvas.cpp 3 + + We get three kind of events to this function: TabletPress, + TabletRelease, and TabletMove, which is generated when a device + is pressed down on, leaves, or moves on the tablet. We set the \c + deviceDown to true when a device is pressed down on the tablet; + we then know when we should draw when we receive move events. We + have implemented the \c updateBrush() and \c paintPixmap() helper + functions to update \c myBrush and \c myPen after the state of \c + alphaChannelType, \c colorSaturationType, and \c lineWidthType. + + Here is the implementation of \c paintEvent(): + + \snippet examples/widgets/tablet/tabletcanvas.cpp 4 + + We simply draw the pixmap to the top left of the widget. + + Here is the implementation of \c paintPixmap(): + + \snippet examples/widgets/tablet/tabletcanvas.cpp 5 + + In this function we draw on the pixmap based on the movement of the + device. If the device used on the tablet is a stylus we want to draw a + line between the positions of the stylus recorded in \c polyLine. We + also assume that this is a reasonable handling of any unknown device, + but update the statusbar with a warning so that the user can see that + for his tablet he might have to implement special handling. + If it is an airbrush we want to draw a circle of points with a + point density based on the tangential pressure, which is the position + of the finger wheel on the airbrush. We use the Qt::BrushStyle to + draw the points as it has styles that draw points with different + density; we select the style based on the tangential pressure in + \c brushPattern(). + + \snippet examples/widgets/tablet/tabletcanvas.cpp 6 + + We return a brush style with a point density that increases with + the tangential pressure. + + In \c updateBrush() we set the pen and brush used for drawing + to match \c alphaChannelType, \c lineWidthType, \c + colorSaturationType, and \c myColor. We will examine the code to + set up \c myBrush and \c myPen for each of these variables: + + \snippet examples/widgets/tablet/tabletcanvas.cpp 7 + + We fetch the current drawingcolor's hue, saturation, value, + and alpha values. \c hValue and \c vValue are set to the + horizontal and vertical tilt as a number from 0 to 255. The + original values are in degrees from -60 to 60, i.e., 0 equals + -60, 127 equals 0, and 255 equals 60 degrees. The angle measured + is between the device and the perpendicular of the tablet (see + QTabletEvent for an illustration). + + \snippet examples/widgets/tablet/tabletcanvas.cpp 8 + + The alpha channel of QColor is given as a number between 0 + and 255 where 0 is transparent and 255 is opaque. + \l{QTabletEvent::}{pressure()} returns the pressure as a qreal + between 0.0 and 1.0. By subtracting 127 from the tilt values and + taking the absolute value we get the smallest alpha values (i.e., + the color is most transparent) when the pen is perpendicular to + the tablet. We select the largest of the vertical and horizontal + tilt value. + + \snippet examples/widgets/tablet/tabletcanvas.cpp 9 + + The colorsaturation is given as a number between 0 and 255. It is + set with \l{QColor::}{setHsv()}. We can set the tilt values + directly, but must multiply the pressure to a number between 0 and + 255. + + \snippet examples/widgets/tablet/tabletcanvas.cpp 10 + + The width of the pen increases with the pressure. When the pen + width is controlled with the tilt we let the width increse with + the angle between the device and the perpendicular of the tablet. + + \snippet examples/widgets/tablet/tabletcanvas.cpp 11 + + We finally check wether the pointer is the stylus or the eraser. + If it is the eraser, we set the color to the background color of + the pixmap an let the pressure decide the pen width, else we set + the colors we have set up previously in the function. + + + \section1 TabletApplication Class Definition + + We inherit QApplication in this class because we want to + reimplement the \l{QApplication::}{event()} function. + + \snippet examples/widgets/tablet/tabletapplication.h 0 + + We keep a \c TabletCanvas we send the device type of the events we + handle in the \c event() function to. The TabletEnterProximity + and TabletLeaveProximity events are not sendt to the QApplication + object, while other tablet events are sendt to the QWidget's + \c event(), which sends them on to \l{QWidget::}{tabletEvent()}. + Since we want to handle these events we have implemented \c + TabletApplication. + + + \section1 TabletApplication Class Implementation + + Here is the implementation of \c event(): + + \snippet examples/widgets/tablet/tabletapplication.cpp 0 + + We use this function to handle the TabletEnterProximity and + TabletLeaveProximity events, which is generated when a device + enters and leaves the proximity of the tablet. The intended use of these + events is to do work that is dependent on what kind of device is + used on the tablet. This way, you don't have to do this work + when other events are generated, which is more frequently than the + leave and enter proximity events. We call \c setTabletDevice() in + \c TabletCanvas. + + \section1 The \c main() function + + Here is the examples \c main() function: + + \snippet examples/widgets/tablet/main.cpp 0 + + In the \c main() function we create a \c MainWinow and display it + as a top level window. We use the \c TabletApplication class. We + need to set the canvas after the application is created. We cannot + use classes that implement event handling before an QApplication + object is instantiated. +*/