Sophie

Sophie

distrib > Fedora > 18 > x86_64 > by-pkgid > ff187cb994c94c614ecc64c5a8528b1b > files > 8069

qt-doc-4.8.5-10.fc18.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- tablet.qdoc -->
  <title>Qt 4.8: Tablet Example</title>
  <link rel="stylesheet" type="text/css" href="style/style.css" />
  <script src="scripts/jquery.js" type="text/javascript"></script>
  <script src="scripts/functions.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="style/superfish.css" />
  <link rel="stylesheet" type="text/css" href="style/narrow.css" />
  <!--[if IE]>
<meta name="MSSmartTagsPreventParsing" content="true">
<meta http-equiv="imagetoolbar" content="no">
<![endif]-->
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie6.css">
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie7.css">
<![endif]-->
<!--[if IE 8]>
<link rel="stylesheet" type="text/css" href="style/style_ie8.css">
<![endif]-->

<script src="scripts/superfish.js" type="text/javascript"></script>
<script src="scripts/narrow.js" type="text/javascript"></script>

</head>
<body class="" onload="CheckEmptyAndLoadList();">
 <div class="header" id="qtdocheader">
    <div class="content"> 
    <div id="nav-logo">
      <a href="index.html">Home</a></div>
    <a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
    <div id="narrowsearch"></div>
    <div id="nav-topright">
      <ul>
        <li class="nav-topright-home"><a href="http://qt.digia.com/">Qt HOME</a></li>
        <li class="nav-topright-dev"><a href="http://qt-project.org/">DEV</a></li>
        <li class="nav-topright-doc nav-topright-doc-active"><a href="http://qt-project.org/doc/">
          DOC</a></li>
        <li class="nav-topright-blog"><a href="http://blog.qt.digia.com/">BLOG</a></li>
      </ul>
    </div>
    <div id="shortCut">
      <ul>
        <li class="shortCut-topleft-inactive"><span><a href="index.html">Qt 4.8</a></span></li>
        <li class="shortCut-topleft-active"><a href="http://qt-project.org/doc/">ALL VERSIONS        </a></li>
      </ul>
     </div>
 <ul class="sf-menu" id="narrowmenu"> 
             <li><a href="#">API Lookup</a> 
                 <ul> 
                     <li><a href="classes.html">Class index</a></li> 
           <li><a href="functions.html">Function index</a></li> 
           <li><a href="modules.html">Modules</a></li> 
           <li><a href="namespaces.html">Namespaces</a></li> 
           <li><a href="qtglobal.html">Global Declarations</a></li> 
           <li><a href="qdeclarativeelements.html">QML elements</a></li> 
             </ul> 
             </li> 
             <li><a href="#">Qt Topics</a> 
                 <ul> 
                        <li><a href="qt-basic-concepts.html">Programming with Qt</a></li>  
                        <li><a href="qtquick.html">Device UIs &amp; Qt Quick</a></li>  
                        <li><a href="qt-gui-concepts.html">UI Design with Qt</a></li>  
                        <li><a href="supported-platforms.html">Supported Platforms</a></li>  
                        <li><a href="technology-apis.html">Qt and Key Technologies</a></li>  
                        <li><a href="best-practices.html">How-To's and Best Practices</a></li>  
              </ul> 
                 </li> 
                 <li><a href="#">Examples</a> 
                     <ul> 
                       <li><a href="all-examples.html">Examples</a></li> 
                       <li><a href="tutorials.html">Tutorials</a></li> 
                       <li><a href="demos.html">Demos</a></li> 
                       <li><a href="qdeclarativeexamples.html">QML Examples</a></li> 
                </ul> 
                     </li> 
                 </ul> 
    </div>
  </div>
  <div class="wrapper">
    <div class="hd">
      <span></span>
    </div>
    <div class="bd group">
      <div class="sidebar">
        <div class="searchlabel">
          Search index:</div>
        <div class="search" id="sidebarsearch">
          <form id="qtdocsearch" action="" onsubmit="return false;">
            <fieldset>
              <input type="text" name="searchstring" id="pageType" value="" />
 <div id="resultdialog"> 
 <a href="#" id="resultclose">Close</a> 
 <p id="resultlinks" class="all"><a href="#" id="showallresults">All</a> | <a href="#" id="showapiresults">API</a> | <a href="#" id="showarticleresults">Articles</a> | <a href="#" id="showexampleresults">Examples</a></p> 
 <p id="searchcount" class="all"><span id="resultcount"></span><span id="apicount"></span><span id="articlecount"></span><span id="examplecount"></span>&nbsp;results:</p> 
 <ul id="resultlist" class="all"> 
 </ul> 
 </div> 
            </fieldset>
          </form>
        </div>
        <div class="box first bottombar" id="lookup">
          <h2 title="API Lookup"><span></span>
            API Lookup</h2>
          <div  id="list001" class="list">
          <ul id="ul001" >
              <li class="defaultLink"><a href="classes.html">Class index</a></li>
              <li class="defaultLink"><a href="functions.html">Function index</a></li>
              <li class="defaultLink"><a href="modules.html">Modules</a></li>
              <li class="defaultLink"><a href="namespaces.html">Namespaces</a></li>
              <li class="defaultLink"><a href="qtglobal.html">Global Declarations</a></li>
              <li class="defaultLink"><a href="qdeclarativeelements.html">QML elements</a></li>
            </ul> 
          </div>
        </div>
        <div class="box bottombar" id="topics">
          <h2 title="Qt Topics"><span></span>
            Qt Topics</h2>
          <div id="list002" class="list">
            <ul id="ul002" >
               <li class="defaultLink"><a href="qt-basic-concepts.html">Programming with Qt</a></li> 
               <li class="defaultLink"><a href="qtquick.html">Device UIs &amp; Qt Quick</a></li> 
               <li class="defaultLink"><a href="qt-gui-concepts.html">UI Design with Qt</a></li> 
               <li class="defaultLink"><a href="supported-platforms.html">Supported Platforms</a></li>  
               <li class="defaultLink"><a href="technology-apis.html">Qt and Key Technologies</a></li> 
               <li class="defaultLink"><a href="best-practices.html">How-To's and Best Practices</a></li> 
            </ul>  
          </div>
        </div>
        <div class="box" id="examples">
          <h2 title="Examples"><span></span>
            Examples</h2>
          <div id="list003" class="list">
        <ul id="ul003">
              <li class="defaultLink"><a href="all-examples.html">Examples</a></li>
              <li class="defaultLink"><a href="tutorials.html">Tutorials</a></li>
              <li class="defaultLink"><a href="demos.html">Demos</a></li>
              <li class="defaultLink"><a href="qdeclarativeexamples.html">QML Examples</a></li>
            </ul> 
          </div>
        </div>
      </div>
      <div class="wrap">
        <div class="toolbar">
          <div class="breadcrumb toolblock">
            <ul>
              <li class="first"><a href="index.html">Home</a></li>
              <!--  Breadcrumbs go here -->
<li><a href="all-examples.html">Examples</a></li>
<li>Tablet Example</li>
            </ul>
          </div>
          <div class="toolbuttons toolblock">
            <ul>
              <li id="smallA" class="t_button">A</li>
              <li id="medA" class="t_button active">A</li>
              <li id="bigA" class="t_button">A</li>
              <li id="print" class="t_button"><a href="javascript:this.print();">
                <span>Print</span></a></li>
            </ul>
        </div>
        </div>
        <div class="content mainContent">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#mainwindow-class-definition">MainWindow Class Definition</a></li>
<li class="level1"><a href="#mainwindow-class-implementation">MainWindow Class Implementation</a></li>
<li class="level1"><a href="#tabletcanvas-class-definition">TabletCanvas Class Definition</a></li>
<li class="level1"><a href="#tabletcanvas-class-implementation">TabletCanvas Class Implementation</a></li>
<li class="level1"><a href="#tabletapplication-class-definition">TabletApplication Class Definition</a></li>
<li class="level1"><a href="#tabletapplication-class-implementation">TabletApplication Class Implementation</a></li>
<li class="level1"><a href="#the-function">The <tt>main()</tt> function</a></li>
</ul>
</div>
<h1 class="title">Tablet Example</h1>
<span class="subtitle"></span>
<!-- $$$widgets/tablet-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="widgets-tablet-mainwindow-cpp.html">widgets/tablet/mainwindow.cpp</a></li>
<li><a href="widgets-tablet-mainwindow-h.html">widgets/tablet/mainwindow.h</a></li>
<li><a href="widgets-tablet-tabletapplication-cpp.html">widgets/tablet/tabletapplication.cpp</a></li>
<li><a href="widgets-tablet-tabletapplication-h.html">widgets/tablet/tabletapplication.h</a></li>
<li><a href="widgets-tablet-tabletcanvas-cpp.html">widgets/tablet/tabletcanvas.cpp</a></li>
<li><a href="widgets-tablet-tabletcanvas-h.html">widgets/tablet/tabletcanvas.h</a></li>
<li><a href="widgets-tablet-main-cpp.html">widgets/tablet/main.cpp</a></li>
<li><a href="widgets-tablet-tablet-pro.html">widgets/tablet/tablet.pro</a></li>
</ul>
<p>The Tablet example shows how to use a Wacom tablet in Qt applications.<p class="centerAlign"><img src="images/tabletexample.png" alt="" /></p><p>When you use a tablet with Qt applications, <a href="qtabletevent.html">QTabletEvent</a>s are generated. You need to reimplement the <a href="qwidget.html#tabletEvent">tabletEvent()</a> 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&#x2e;, 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.</p>
<p>The information available in <a href="qtabletevent.html">QTabletEvent</a> 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.</p>
<p>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 <a href="qcolor.html">QColor</a> and the width of the <a href="qpen.html">QPen</a> used for drawing.</p>
<p>The example consists of the following:</p>
<ul>
<li>The <tt>MainWindow</tt> class inherits <a href="qmainwindow.html">QMainWindow</a> and creates the examples menus and connect their slots and signals.</li>
<li>The <tt>TabletCanvas</tt> class inherits <a href="qwidget.html">QWidget</a> and receives tablet events. It uses the events to paint on a offscreen pixmap, which it draws onto itself.</li>
<li>The <tt>TabletApplication</tt> class inherits <a href="qapplication.html">QApplication</a>. This class handles tablet events that are not sent to <tt>tabletEvent()</tt>. We will look at this later.</li>
<li>The <tt>main()</tt> function creates a <tt>MainWindow</tt> and shows it as a top level window.</li>
</ul>
<a name="mainwindow-class-definition"></a>
<h2>MainWindow Class Definition</h2>
<p>The <tt>MainWindow</tt> creates a <tt>TabletCanvas</tt> and sets it as its center widget.</p>
<pre class="cpp"> <span class="keyword">class</span> MainWindow : <span class="keyword">public</span> <span class="type"><a href="qmainwindow.html">QMainWindow</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     MainWindow(TabletCanvas <span class="operator">*</span>canvas);

 <span class="keyword">private</span> <span class="keyword">slots</span>:
     <span class="type">void</span> brushColorAct();
     <span class="type">void</span> alphaActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action);
     <span class="type">void</span> lineWidthActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action);
     <span class="type">void</span> saturationActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action);
     <span class="type">void</span> saveAct();
     <span class="type">void</span> loadAct();
     <span class="type">void</span> aboutAct();

 <span class="keyword">private</span>:
     <span class="type">void</span> createActions();
     <span class="type">void</span> createMenus();

     TabletCanvas <span class="operator">*</span>myCanvas;

     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>brushColorAction;
     <span class="type"><a href="qactiongroup.html">QActionGroup</a></span> <span class="operator">*</span>brushActionGroup;

     <span class="type"><a href="qactiongroup.html">QActionGroup</a></span> <span class="operator">*</span>alphaChannelGroup;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>alphaChannelPressureAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>alphaChannelTiltAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>noAlphaChannelAction;

     <span class="type"><a href="qactiongroup.html">QActionGroup</a></span> <span class="operator">*</span>colorSaturationGroup;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>colorSaturationVTiltAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>colorSaturationHTiltAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>colorSaturationPressureAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>noColorSaturationAction;

     <span class="type"><a href="qactiongroup.html">QActionGroup</a></span> <span class="operator">*</span>lineWidthGroup;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>lineWidthPressureAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>lineWidthTiltAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>lineWidthFixedAction;

     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>exitAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>saveAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>loadAction;

     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>aboutAction;
     <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>aboutQtAction;

     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>fileMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>brushMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>tabletMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>helpMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>colorSaturationMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>lineWidthMenu;
     <span class="type"><a href="qmenu.html">QMenu</a></span> <span class="operator">*</span>alphaChannelMenu;
 };</pre>
<p>The QActions let the user select if the tablets pressure and tilt should change the pen width, color alpha component and color saturation. <tt>createActions()</tt> creates all actions, and <tt>createMenus()</tt> sets up the menus with the actions. We have one <a href="qactiongroup.html">QActionGroup</a> for the actions that alter the alpha channel, color saturation and line width respectively. The action groups are connected to the <tt>alphaActionTriggered()</tt>, <tt>colorSaturationActiontriggered()</tt>, and <tt>lineWidthActionTriggered()</tt> slots, which calls functions in <tt>myCanvas</tt>.</p>
<a name="mainwindow-class-implementation"></a>
<h2>MainWindow Class Implementation</h2>
<p>We start width a look at the constructor <tt>MainWindow()</tt>:</p>
<pre class="cpp"> MainWindow<span class="operator">::</span>MainWindow(TabletCanvas <span class="operator">*</span>canvas)
 {
     myCanvas <span class="operator">=</span> canvas;
     createActions();
     createMenus();

     myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColor(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>red);
     myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setLineWidthType(TabletCanvas<span class="operator">::</span>LineWidthPressure);
     myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setAlphaChannelType(TabletCanvas<span class="operator">::</span>NoAlpha);
     myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColorSaturationType(TabletCanvas<span class="operator">::</span>NoSaturation);

     setWindowTitle(tr(<span class="string">&quot;Tablet Example&quot;</span>));
     setCentralWidget(myCanvas);
 }</pre>
<p>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.</p>
<p>Here is the implementation of <tt>brushColorAct()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>brushColorAct()
 {
     <span class="type"><a href="qcolor.html">QColor</a></span> color <span class="operator">=</span> <span class="type"><a href="qcolordialog.html">QColorDialog</a></span><span class="operator">::</span>getColor(myCanvas<span class="operator">-</span><span class="operator">&gt;</span>color());

     <span class="keyword">if</span> (color<span class="operator">.</span>isValid())
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColor(color);
 }</pre>
<p>We let the user pick a color with a <a href="qcolordialog.html">QColorDialog</a>. If it is valid, we set a new drawing color with <tt>setColor()</tt>.</p>
<p>Here is the implementation of <tt>alphaActionTriggered()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>alphaActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action)
 {
     <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> alphaChannelPressureAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setAlphaChannelType(TabletCanvas<span class="operator">::</span>AlphaPressure);
     } <span class="keyword">else</span> <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> alphaChannelTiltAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setAlphaChannelType(TabletCanvas<span class="operator">::</span>AlphaTilt);
     } <span class="keyword">else</span> {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setAlphaChannelType(TabletCanvas<span class="operator">::</span>NoAlpha);
     }
 }</pre>
<p>The <tt>TabletCanvas</tt> 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.</p>
<p>Here is the implementation of <tt>lineWidthActionTriggered()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>lineWidthActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action)
 {
     <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> lineWidthPressureAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setLineWidthType(TabletCanvas<span class="operator">::</span>LineWidthPressure);
     } <span class="keyword">else</span> <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> lineWidthTiltAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setLineWidthType(TabletCanvas<span class="operator">::</span>LineWidthTilt);
     } <span class="keyword">else</span> {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setLineWidthType(TabletCanvas<span class="operator">::</span>NoLineWidth);
     }
 }</pre>
<p>We check which action is selected in <tt>lineWidthGroup</tt>, and set how the canvas should change the drawing line width.</p>
<p>Here is the implementation of <tt>saturationActionTriggered()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>saturationActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action)
 {
     <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> colorSaturationVTiltAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColorSaturationType(TabletCanvas<span class="operator">::</span>SaturationVTilt);
     } <span class="keyword">else</span> <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> colorSaturationHTiltAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColorSaturationType(TabletCanvas<span class="operator">::</span>SaturationHTilt);
     } <span class="keyword">else</span> <span class="keyword">if</span> (action <span class="operator">=</span><span class="operator">=</span> colorSaturationPressureAction) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColorSaturationType(TabletCanvas<span class="operator">::</span>SaturationPressure);
     } <span class="keyword">else</span> {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setColorSaturationType(TabletCanvas<span class="operator">::</span>NoSaturation);
     }
 }</pre>
<p>We check which action is selected in <tt>colorSaturationGroup</tt>, and set how the canvas should change the color saturation of the drawing color.</p>
<p>Here is the implementation of <tt>saveAct()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>saveAct()
 {
     <span class="type"><a href="qstring.html">QString</a></span> path <span class="operator">=</span> <span class="type"><a href="qdir.html">QDir</a></span><span class="operator">::</span>currentPath() <span class="operator">+</span> <span class="string">&quot;/untitled.png&quot;</span>;
     <span class="type"><a href="qstring.html">QString</a></span> fileName <span class="operator">=</span> <span class="type"><a href="qfiledialog.html">QFileDialog</a></span><span class="operator">::</span>getSaveFileName(<span class="keyword">this</span><span class="operator">,</span> tr(<span class="string">&quot;Save Picture&quot;</span>)<span class="operator">,</span>
                              path);

     <span class="keyword">if</span> (<span class="operator">!</span>myCanvas<span class="operator">-</span><span class="operator">&gt;</span>saveImage(fileName))
         <span class="type"><a href="qmessagebox.html">QMessageBox</a></span><span class="operator">::</span>information(<span class="keyword">this</span><span class="operator">,</span> <span class="string">&quot;Error Saving Picture&quot;</span><span class="operator">,</span>
                                  <span class="string">&quot;Could not save the image&quot;</span>);
 }</pre>
<p>We use the <a href="qfiledialog.html">QFileDialog</a> to let the user select a file to save the drawing in. It is the <tt>TabletCanvas</tt> that save the drawing, so we call its <tt>saveImage()</tt> function.</p>
<p>Here is the implementation of <tt>loadAct()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>loadAct()
 {
     <span class="type"><a href="qstring.html">QString</a></span> fileName <span class="operator">=</span> <span class="type"><a href="qfiledialog.html">QFileDialog</a></span><span class="operator">::</span>getOpenFileName(<span class="keyword">this</span><span class="operator">,</span> tr(<span class="string">&quot;Open Picture&quot;</span>)<span class="operator">,</span>
                                                     <span class="type"><a href="qdir.html">QDir</a></span><span class="operator">::</span>currentPath());

     <span class="keyword">if</span> (<span class="operator">!</span>myCanvas<span class="operator">-</span><span class="operator">&gt;</span>loadImage(fileName))
         <span class="type"><a href="qmessagebox.html">QMessageBox</a></span><span class="operator">::</span>information(<span class="keyword">this</span><span class="operator">,</span> <span class="string">&quot;Error Opening Picture&quot;</span><span class="operator">,</span>
                                  <span class="string">&quot;Could not open picture&quot;</span>);
 }</pre>
<p>We let the user select the image file to be opened with a <a href="qfiledialog.html">QFileDialog</a>; we then ask the canvas to load the image with <tt>loadImage()</tt>.</p>
<p>Here is the implementation of <tt>aboutAct()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>aboutAct()
 {
     <span class="type"><a href="qmessagebox.html">QMessageBox</a></span><span class="operator">::</span>about(<span class="keyword">this</span><span class="operator">,</span> tr(<span class="string">&quot;About Tablet Example&quot;</span>)<span class="operator">,</span>
                        tr(<span class="string">&quot;This example shows use of a Wacom tablet in Qt&quot;</span>));
 }</pre>
<p>We show a message box with a short description of the example.</p>
<p><tt>createActions()</tt> creates all actions and action groups of the example. We look at the creation of one action group and its actions. See the <a href="mainwindows-application.html">application example</a> if you want a high-level introduction to QActions.</p>
<p>Here is the implementation of <tt>createActions</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>createActions()
 {
     ...
     alphaChannelPressureAction <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qaction.html">QAction</a></span>(tr(<span class="string">&quot;&amp;Pressure&quot;</span>)<span class="operator">,</span> <span class="keyword">this</span>);
     alphaChannelPressureAction<span class="operator">-</span><span class="operator">&gt;</span>setCheckable(<span class="keyword">true</span>);

     alphaChannelTiltAction <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qaction.html">QAction</a></span>(tr(<span class="string">&quot;&amp;Tilt&quot;</span>)<span class="operator">,</span> <span class="keyword">this</span>);
     alphaChannelTiltAction<span class="operator">-</span><span class="operator">&gt;</span>setCheckable(<span class="keyword">true</span>);

     noAlphaChannelAction <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qaction.html">QAction</a></span>(tr(<span class="string">&quot;No Alpha Channel&quot;</span>)<span class="operator">,</span> <span class="keyword">this</span>);
     noAlphaChannelAction<span class="operator">-</span><span class="operator">&gt;</span>setCheckable(<span class="keyword">true</span>);
     noAlphaChannelAction<span class="operator">-</span><span class="operator">&gt;</span>setChecked(<span class="keyword">true</span>);

     alphaChannelGroup <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qactiongroup.html">QActionGroup</a></span>(<span class="keyword">this</span>);
     alphaChannelGroup<span class="operator">-</span><span class="operator">&gt;</span>addAction(alphaChannelPressureAction);
     alphaChannelGroup<span class="operator">-</span><span class="operator">&gt;</span>addAction(alphaChannelTiltAction);
     alphaChannelGroup<span class="operator">-</span><span class="operator">&gt;</span>addAction(noAlphaChannelAction);
     connect(alphaChannelGroup<span class="operator">,</span> SIGNAL(triggered(<span class="type"><a href="qaction.html">QAction</a></span><span class="operator">*</span>))<span class="operator">,</span>
             <span class="keyword">this</span><span class="operator">,</span> SLOT(alphaActionTriggered(<span class="type"><a href="qaction.html">QAction</a></span><span class="operator">*</span>)));</pre>
<p>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 <tt>alphaChannelGroup</tt> will then ensure that only one of the actions are checked at any time. The <tt>triggered()</tt> signal is emitted when an action is checked.</p>
<pre class="qml">     ...
 }</pre>
<p>Here is the implementation of <tt>createMenus()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> MainWindow<span class="operator">::</span>createMenus()
 {
     fileMenu <span class="operator">=</span> menuBar()<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;File&quot;</span>));
     fileMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(loadAction);
     fileMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(saveAction);
     fileMenu<span class="operator">-</span><span class="operator">&gt;</span>addSeparator();
     fileMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(exitAction);

     brushMenu <span class="operator">=</span> menuBar()<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;Brush&quot;</span>));
     brushMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(brushColorAction);

     tabletMenu <span class="operator">=</span> menuBar()<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;Tablet&quot;</span>));

     lineWidthMenu <span class="operator">=</span> tabletMenu<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;Line Width&quot;</span>));
     lineWidthMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(lineWidthPressureAction);
     lineWidthMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(lineWidthTiltAction);
     lineWidthMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(lineWidthFixedAction);

     alphaChannelMenu <span class="operator">=</span> tabletMenu<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;Alpha Channel&quot;</span>));
     alphaChannelMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(alphaChannelPressureAction);
     alphaChannelMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(alphaChannelTiltAction);
     alphaChannelMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(noAlphaChannelAction);

     colorSaturationMenu <span class="operator">=</span> tabletMenu<span class="operator">-</span><span class="operator">&gt;</span>addMenu(tr(<span class="string">&quot;&amp;Color Saturation&quot;</span>));
     colorSaturationMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(colorSaturationVTiltAction);
     colorSaturationMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(colorSaturationHTiltAction);
     colorSaturationMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(noColorSaturationAction);

     helpMenu <span class="operator">=</span> menuBar()<span class="operator">-</span><span class="operator">&gt;</span>addMenu(<span class="string">&quot;&amp;Help&quot;</span>);
     helpMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(aboutAction);
     helpMenu<span class="operator">-</span><span class="operator">&gt;</span>addAction(aboutQtAction);
 }</pre>
<p>We create the menus of the example and add the actions to them.</p>
<a name="tabletcanvas-class-definition"></a>
<h2>TabletCanvas Class Definition</h2>
<p>The <tt>TabletCanvas</tt> class provides a surface on which the user can draw with a tablet.</p>
<pre class="cpp"> <span class="keyword">class</span> TabletCanvas : <span class="keyword">public</span> <span class="type"><a href="qwidget.html">QWidget</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     <span class="keyword">enum</span> AlphaChannelType { AlphaPressure<span class="operator">,</span> AlphaTilt<span class="operator">,</span> NoAlpha };
     <span class="keyword">enum</span> ColorSaturationType { SaturationVTilt<span class="operator">,</span> SaturationHTilt<span class="operator">,</span>
                                SaturationPressure<span class="operator">,</span> NoSaturation };
     <span class="keyword">enum</span> LineWidthType { LineWidthPressure<span class="operator">,</span> LineWidthTilt<span class="operator">,</span> NoLineWidth };

     TabletCanvas();

     <span class="type">bool</span> saveImage(<span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> <span class="operator">&amp;</span>file);
     <span class="type">bool</span> loadImage(<span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> <span class="operator">&amp;</span>file);
     <span class="type">void</span> setAlphaChannelType(AlphaChannelType type)
         { alphaChannelType <span class="operator">=</span> type; }
     <span class="type">void</span> setColorSaturationType(ColorSaturationType type)
         { colorSaturationType <span class="operator">=</span> type; }
     <span class="type">void</span> setLineWidthType(LineWidthType type)
         { lineWidthType <span class="operator">=</span> type; }
     <span class="type">void</span> setColor(<span class="keyword">const</span> <span class="type"><a href="qcolor.html">QColor</a></span> <span class="operator">&amp;</span>color)
         { myColor <span class="operator">=</span> color; }
     <span class="type"><a href="qcolor.html">QColor</a></span> color() <span class="keyword">const</span>
         { <span class="keyword">return</span> myColor; }
     <span class="type">void</span> setTabletDevice(<span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>TabletDevice device)
         { myTabletDevice <span class="operator">=</span> device; }
     <span class="type">int</span> maximum(<span class="type">int</span> a<span class="operator">,</span> <span class="type">int</span> b)
         { <span class="keyword">return</span> a <span class="operator">&gt;</span> b <span class="operator">?</span> a : b; }

 <span class="keyword">protected</span>:
     <span class="type">void</span> tabletEvent(<span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event);
     <span class="type">void</span> paintEvent(<span class="type"><a href="qpaintevent.html">QPaintEvent</a></span> <span class="operator">*</span>event);
     <span class="type">void</span> resizeEvent(<span class="type"><a href="qresizeevent.html">QResizeEvent</a></span> <span class="operator">*</span>event);

 <span class="keyword">private</span>:
     <span class="type">void</span> initPixmap();
     <span class="type">void</span> paintPixmap(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">&amp;</span>painter<span class="operator">,</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event);
     <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>BrushStyle brushPattern(<span class="type"><a href="qtglobal.html#qreal-typedef">qreal</a></span> value);
     <span class="type">void</span> updateBrush(<span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event);

     AlphaChannelType alphaChannelType;
     ColorSaturationType colorSaturationType;
     LineWidthType lineWidthType;
     <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>PointerType pointerType;
     <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>TabletDevice myTabletDevice;
     <span class="type"><a href="qcolor.html">QColor</a></span> myColor;

     <span class="type"><a href="qpixmap.html">QPixmap</a></span> pixmap;
     <span class="type"><a href="qbrush.html">QBrush</a></span> myBrush;
     <span class="type"><a href="qpen.html">QPen</a></span> myPen;
     <span class="type">bool</span> deviceDown;
     <span class="type"><a href="qpoint.html">QPoint</a></span> polyLine<span class="operator">[</span><span class="number">3</span><span class="operator">]</span>;
 };</pre>
<p>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 <tt>alphaChannelType</tt>, <tt>colorSturationType</tt>, and <tt>penWidthType</tt>, which we provide access functions for.</p>
<p>We draw on a <a href="qpixmap.html">QPixmap</a> with <tt>myPen</tt> and <tt>myBrush</tt> using <tt>myColor</tt>. The <tt>saveImage()</tt> and <tt>loadImage()</tt> saves and loads the <a href="qpixmap.html">QPixmap</a> to disk. The pixmap is drawn on the widget in <tt>paintEvent()</tt>. The <tt>pointerType</tt> and <tt>deviceType</tt> 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.</p>
<p>The interpretation of events from the tablet is done in <tt>tabletEvent()</tt>; <tt>paintPixmap()</tt>, <tt>updateBrush()</tt>, and <tt>brushPattern()</tt> are helper functions used by <tt>tabletEvent()</tt>.</p>
<a name="tabletcanvas-class-implementation"></a>
<h2>TabletCanvas Class Implementation</h2>
<p>We start with a look at the constructor:</p>
<pre class="cpp"> TabletCanvas<span class="operator">::</span>TabletCanvas()
 {
     resize(<span class="number">500</span><span class="operator">,</span> <span class="number">500</span>);
     myBrush <span class="operator">=</span> <span class="type"><a href="qbrush.html">QBrush</a></span>();
     myPen <span class="operator">=</span> <span class="type"><a href="qpen.html">QPen</a></span>();
     initPixmap();
     setAutoFillBackground(<span class="keyword">true</span>);
     deviceDown <span class="operator">=</span> <span class="keyword">false</span>;
     myColor <span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>red;
     myTabletDevice <span class="operator">=</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>Stylus;
     alphaChannelType <span class="operator">=</span> NoAlpha;
     colorSaturationType <span class="operator">=</span> NoSaturation;
     lineWidthType <span class="operator">=</span> LineWidthPressure;
 }

 <span class="type">void</span> TabletCanvas<span class="operator">::</span>initPixmap()
 {
     <span class="type"><a href="qpixmap.html">QPixmap</a></span> newPixmap <span class="operator">=</span> <span class="type"><a href="qpixmap.html">QPixmap</a></span>(width()<span class="operator">,</span> height());
     newPixmap<span class="operator">.</span>fill(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>white);
     <span class="type"><a href="qpainter.html">QPainter</a></span> painter(<span class="operator">&amp;</span>newPixmap);
     <span class="keyword">if</span> (<span class="operator">!</span>pixmap<span class="operator">.</span>isNull())
         painter<span class="operator">.</span>drawPixmap(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> pixmap);
     painter<span class="operator">.</span>end();
     pixmap <span class="operator">=</span> newPixmap;
 }</pre>
<p>In the constructor we initialize our class variables. We need to draw the background of our pixmap, as the default is gray.</p>
<p>Here is the implementation of <tt>saveImage()</tt>:</p>
<pre class="cpp"> <span class="type">bool</span> TabletCanvas<span class="operator">::</span>saveImage(<span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> <span class="operator">&amp;</span>file)
 {
     <span class="keyword">return</span> pixmap<span class="operator">.</span>save(file);
 }</pre>
<p><a href="qpixmap.html">QPixmap</a> implements functionality to save itself to disk, so we simply call <a href="qpixmap.html#save">save()</a>.</p>
<p>Here is the implementation of <tt>loadImage()</tt>:</p>
<pre class="cpp"> <span class="type">bool</span> TabletCanvas<span class="operator">::</span>loadImage(<span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> <span class="operator">&amp;</span>file)
 {
     <span class="type">bool</span> success <span class="operator">=</span> pixmap<span class="operator">.</span>load(file);

     <span class="keyword">if</span> (success) {
         update();
         <span class="keyword">return</span> <span class="keyword">true</span>;
     }
     <span class="keyword">return</span> <span class="keyword">false</span>;
 }</pre>
<p>We simply call <a href="qpixmap.html#load">load()</a>, which loads the image in <i>file</i>.</p>
<p>Here is the implementation of <tt>tabletEvent()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> TabletCanvas<span class="operator">::</span>tabletEvent(<span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event)
 {

     <span class="keyword">switch</span> (event<span class="operator">-</span><span class="operator">&gt;</span>type()) {
         <span class="keyword">case</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>TabletPress:
             <span class="keyword">if</span> (<span class="operator">!</span>deviceDown) {
                 deviceDown <span class="operator">=</span> <span class="keyword">true</span>;
                 polyLine<span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> polyLine<span class="operator">[</span><span class="number">1</span><span class="operator">]</span> <span class="operator">=</span> polyLine<span class="operator">[</span><span class="number">2</span><span class="operator">]</span> <span class="operator">=</span> event<span class="operator">-</span><span class="operator">&gt;</span>pos();
             }
             <span class="keyword">break</span>;
         <span class="keyword">case</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>TabletRelease:
             <span class="keyword">if</span> (deviceDown)
                 deviceDown <span class="operator">=</span> <span class="keyword">false</span>;
             <span class="keyword">break</span>;
         <span class="keyword">case</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>TabletMove:
             polyLine<span class="operator">[</span><span class="number">2</span><span class="operator">]</span> <span class="operator">=</span> polyLine<span class="operator">[</span><span class="number">1</span><span class="operator">]</span>;
             polyLine<span class="operator">[</span><span class="number">1</span><span class="operator">]</span> <span class="operator">=</span> polyLine<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>;
             polyLine<span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> event<span class="operator">-</span><span class="operator">&gt;</span>pos();

             <span class="keyword">if</span> (deviceDown) {
                 updateBrush(event);
                 <span class="type"><a href="qpainter.html">QPainter</a></span> painter(<span class="operator">&amp;</span>pixmap);
                 paintPixmap(painter<span class="operator">,</span> event);
             }
             <span class="keyword">break</span>;
         <span class="keyword">default</span>:
             <span class="keyword">break</span>;
     }
     update();
 }</pre>
<p>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 <tt>deviceDown</tt> 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 <tt>updateBrush()</tt> and <tt>paintPixmap()</tt> helper functions to update <tt>myBrush</tt> and <tt>myPen</tt> after the state of <tt>alphaChannelType</tt>, <tt>colorSaturationType</tt>, and <tt>lineWidthType</tt>.</p>
<p>Here is the implementation of <tt>paintEvent()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> TabletCanvas<span class="operator">::</span>paintEvent(<span class="type"><a href="qpaintevent.html">QPaintEvent</a></span> <span class="operator">*</span>)
 {
     <span class="type"><a href="qpainter.html">QPainter</a></span> painter(<span class="keyword">this</span>);
     painter<span class="operator">.</span>drawPixmap(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> pixmap);
 }</pre>
<p>We simply draw the pixmap to the top left of the widget.</p>
<p>Here is the implementation of <tt>paintPixmap()</tt>:</p>
<pre class="cpp"> <span class="type">void</span> TabletCanvas<span class="operator">::</span>paintPixmap(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">&amp;</span>painter<span class="operator">,</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event)
 {
     <span class="type"><a href="qpoint.html">QPoint</a></span> brushAdjust(<span class="number">10</span><span class="operator">,</span> <span class="number">10</span>);

     <span class="keyword">switch</span> (myTabletDevice) {
         <span class="keyword">case</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>Airbrush:
             myBrush<span class="operator">.</span>setColor(myColor);
             myBrush<span class="operator">.</span>setStyle(brushPattern(event<span class="operator">-</span><span class="operator">&gt;</span>pressure()));
             painter<span class="operator">.</span>setPen(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>NoPen);
             painter<span class="operator">.</span>setBrush(myBrush);

             <span class="keyword">for</span> (<span class="type">int</span> i <span class="operator">=</span> <span class="number">0</span>; i <span class="operator">&lt;</span> <span class="number">3</span>; <span class="operator">+</span><span class="operator">+</span>i) {
                 painter<span class="operator">.</span>drawEllipse(<span class="type"><a href="qrect.html">QRect</a></span>(polyLine<span class="operator">[</span>i<span class="operator">]</span> <span class="operator">-</span> brushAdjust<span class="operator">,</span>
                                     polyLine<span class="operator">[</span>i<span class="operator">]</span> <span class="operator">+</span> brushAdjust));
             }
             <span class="keyword">break</span>;
         <span class="keyword">case</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>Puck:
         <span class="keyword">case</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>FourDMouse:
         <span class="keyword">case</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>RotationStylus:
             {
                 <span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> error(tr(<span class="string">&quot;This input device is not supported by the example.&quot;</span>));
 <span class="preprocessor">#ifndef QT_NO_STATUSTIP</span>
                 <span class="type"><a href="qstatustipevent.html">QStatusTipEvent</a></span> status(error);
                 <span class="type"><a href="qapplication.html">QApplication</a></span><span class="operator">::</span>sendEvent(<span class="keyword">this</span><span class="operator">,</span> <span class="operator">&amp;</span>status);
 <span class="preprocessor">#else</span>
                 <a href="qtglobal.html#qWarning">qWarning</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> error;
 <span class="preprocessor">#endif</span>
             }
             <span class="keyword">break</span>;
         <span class="keyword">default</span>:
             {
                 <span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> error(tr(<span class="string">&quot;Unknown tablet device - treating as stylus&quot;</span>));
 <span class="preprocessor">#ifndef QT_NO_STATUSTIP</span>
                 <span class="type"><a href="qstatustipevent.html">QStatusTipEvent</a></span> status(error);
                 <span class="type"><a href="qapplication.html">QApplication</a></span><span class="operator">::</span>sendEvent(<span class="keyword">this</span><span class="operator">,</span> <span class="operator">&amp;</span>status);
 <span class="preprocessor">#else</span>
                 <a href="qtglobal.html#qWarning">qWarning</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> error;
 <span class="preprocessor">#endif</span>
             }
             <span class="comment">// FALL-THROUGH</span>
         <span class="keyword">case</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>Stylus:
             painter<span class="operator">.</span>setBrush(myBrush);
             painter<span class="operator">.</span>setPen(myPen);
             painter<span class="operator">.</span>drawLine(polyLine<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">,</span> event<span class="operator">-</span><span class="operator">&gt;</span>pos());
             <span class="keyword">break</span>;
     }
 }</pre>
<p>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 <tt>polyLine</tt>. 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 <a href="qt.html#BrushStyle-enum">Qt::BrushStyle</a> to draw the points as it has styles that draw points with different density; we select the style based on the tangential pressure in <tt>brushPattern()</tt>.</p>
<pre class="cpp"> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>BrushStyle TabletCanvas<span class="operator">::</span>brushPattern(<span class="type"><a href="qtglobal.html#qreal-typedef">qreal</a></span> value)
 {
     <span class="type">int</span> pattern <span class="operator">=</span> <span class="type">int</span>((value) <span class="operator">*</span> <span class="number">100.0</span>) <span class="operator">%</span> <span class="number">7</span>;

     <span class="keyword">switch</span> (pattern) {
         <span class="keyword">case</span> <span class="number">0</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>SolidPattern;
         <span class="keyword">case</span> <span class="number">1</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense1Pattern;
         <span class="keyword">case</span> <span class="number">2</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense2Pattern;
         <span class="keyword">case</span> <span class="number">3</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense3Pattern;
         <span class="keyword">case</span> <span class="number">4</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense4Pattern;
         <span class="keyword">case</span> <span class="number">5</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense5Pattern;
         <span class="keyword">case</span> <span class="number">6</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense6Pattern;
         <span class="keyword">default</span>:
             <span class="keyword">return</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Dense7Pattern;
     }
 }</pre>
<p>We return a brush style with a point density that increases with the tangential pressure.</p>
<p>In <tt>updateBrush()</tt> we set the pen and brush used for drawing to match <tt>alphaChannelType</tt>, <tt>lineWidthType</tt>, <tt>colorSaturationType</tt>, and <tt>myColor</tt>. We will examine the code to set up <tt>myBrush</tt> and <tt>myPen</tt> for each of these variables:</p>
<pre class="cpp"> <span class="type">void</span> TabletCanvas<span class="operator">::</span>updateBrush(<span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span>event)
 {
     <span class="type">int</span> hue<span class="operator">,</span> saturation<span class="operator">,</span> value<span class="operator">,</span> alpha;
     myColor<span class="operator">.</span>getHsv(<span class="operator">&amp;</span>hue<span class="operator">,</span> <span class="operator">&amp;</span>saturation<span class="operator">,</span> <span class="operator">&amp;</span>value<span class="operator">,</span> <span class="operator">&amp;</span>alpha);

     <span class="type">int</span> vValue <span class="operator">=</span> <span class="type">int</span>(((event<span class="operator">-</span><span class="operator">&gt;</span>yTilt() <span class="operator">+</span> <span class="number">60.0</span>) <span class="operator">/</span> <span class="number">120.0</span>) <span class="operator">*</span> <span class="number">255</span>);
     <span class="type">int</span> hValue <span class="operator">=</span> <span class="type">int</span>(((event<span class="operator">-</span><span class="operator">&gt;</span>xTilt() <span class="operator">+</span> <span class="number">60.0</span>) <span class="operator">/</span> <span class="number">120.0</span>) <span class="operator">*</span> <span class="number">255</span>);</pre>
<p>We fetch the current drawingcolor's hue, saturation, value, and alpha values. <tt>hValue</tt> and <tt>vValue</tt> 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&#x2e;, 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 <a href="qtabletevent.html">QTabletEvent</a> for an illustration).</p>
<pre class="cpp">     <span class="keyword">switch</span> (alphaChannelType) {
         <span class="keyword">case</span> AlphaPressure:
             myColor<span class="operator">.</span>setAlpha(<span class="type">int</span>(event<span class="operator">-</span><span class="operator">&gt;</span>pressure() <span class="operator">*</span> <span class="number">255.0</span>));
             <span class="keyword">break</span>;
         <span class="keyword">case</span> AlphaTilt:
             myColor<span class="operator">.</span>setAlpha(maximum(abs(vValue <span class="operator">-</span> <span class="number">127</span>)<span class="operator">,</span> abs(hValue <span class="operator">-</span> <span class="number">127</span>)));
             <span class="keyword">break</span>;
         <span class="keyword">default</span>:
             myColor<span class="operator">.</span>setAlpha(<span class="number">255</span>);
     }</pre>
<p>The alpha channel of <a href="qcolor.html">QColor</a> is given as a number between 0 and 255 where 0 is transparent and 255 is opaque. <a href="qtabletevent.html#pressure">pressure()</a> returns the pressure as a qreal between 0.0 and 1.0&#x2e; By subtracting 127 from the tilt values and taking the absolute value we get the smallest alpha values (i.e&#x2e;, the color is most transparent) when the pen is perpendicular to the tablet. We select the largest of the vertical and horizontal tilt value.</p>
<pre class="cpp">     <span class="keyword">switch</span> (colorSaturationType) {
         <span class="keyword">case</span> SaturationVTilt:
             myColor<span class="operator">.</span>setHsv(hue<span class="operator">,</span> vValue<span class="operator">,</span> value<span class="operator">,</span> alpha);
             <span class="keyword">break</span>;
         <span class="keyword">case</span> SaturationHTilt:
             myColor<span class="operator">.</span>setHsv(hue<span class="operator">,</span> hValue<span class="operator">,</span> value<span class="operator">,</span> alpha);
             <span class="keyword">break</span>;
         <span class="keyword">case</span> SaturationPressure:
             myColor<span class="operator">.</span>setHsv(hue<span class="operator">,</span> <span class="type">int</span>(event<span class="operator">-</span><span class="operator">&gt;</span>pressure() <span class="operator">*</span> <span class="number">255.0</span>)<span class="operator">,</span> value<span class="operator">,</span> alpha);
             <span class="keyword">break</span>;
         <span class="keyword">default</span>:
             ;
     }</pre>
<p>The colorsaturation is given as a number between 0 and 255. It is set with <a href="qcolor.html#setHsv">setHsv()</a>. We can set the tilt values directly, but must multiply the pressure to a number between 0 and 255.</p>
<pre class="cpp">     <span class="keyword">switch</span> (lineWidthType) {
         <span class="keyword">case</span> LineWidthPressure:
             myPen<span class="operator">.</span>setWidthF(event<span class="operator">-</span><span class="operator">&gt;</span>pressure() <span class="operator">*</span> <span class="number">10</span> <span class="operator">+</span> <span class="number">1</span>);
             <span class="keyword">break</span>;
         <span class="keyword">case</span> LineWidthTilt:
             myPen<span class="operator">.</span>setWidthF(maximum(abs(vValue <span class="operator">-</span> <span class="number">127</span>)<span class="operator">,</span> abs(hValue <span class="operator">-</span> <span class="number">127</span>)) <span class="operator">/</span> <span class="number">12</span>);
             <span class="keyword">break</span>;
         <span class="keyword">default</span>:
             myPen<span class="operator">.</span>setWidthF(<span class="number">1</span>);
     }</pre>
<p>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.</p>
<pre class="cpp">     <span class="keyword">if</span> (event<span class="operator">-</span><span class="operator">&gt;</span>pointerType() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qtabletevent.html">QTabletEvent</a></span><span class="operator">::</span>Eraser) {
         myBrush<span class="operator">.</span>setColor(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>white);
         myPen<span class="operator">.</span>setColor(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>white);
         myPen<span class="operator">.</span>setWidthF(event<span class="operator">-</span><span class="operator">&gt;</span>pressure() <span class="operator">*</span> <span class="number">10</span> <span class="operator">+</span> <span class="number">1</span>);
     } <span class="keyword">else</span> {
         myBrush<span class="operator">.</span>setColor(myColor);
         myPen<span class="operator">.</span>setColor(myColor);
     }
 }</pre>
<p>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.</p>
<a name="tabletapplication-class-definition"></a>
<h2>TabletApplication Class Definition</h2>
<p>We inherit <a href="qapplication.html">QApplication</a> in this class because we want to reimplement the <a href="qapplication.html#event">event()</a> function.</p>
<pre class="cpp"> <span class="keyword">class</span> TabletApplication : <span class="keyword">public</span> <span class="type"><a href="qapplication.html">QApplication</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     TabletApplication(<span class="type">int</span> <span class="operator">&amp;</span>argv<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span><span class="operator">*</span>args)
     : <span class="type"><a href="qapplication.html">QApplication</a></span>(argv<span class="operator">,</span> args) {}

     <span class="type">bool</span> event(<span class="type"><a href="qevent.html">QEvent</a></span> <span class="operator">*</span>event);
     <span class="type">void</span> setCanvas(TabletCanvas <span class="operator">*</span>canvas)
         { myCanvas <span class="operator">=</span> canvas; }

 <span class="keyword">private</span>:
     TabletCanvas <span class="operator">*</span>myCanvas;
 };</pre>
<p>We keep a <tt>TabletCanvas</tt> we send the device type of the events we handle in the <tt>event()</tt> function to. The TabletEnterProximity and TabletLeaveProximity events are not sendt to the <a href="qapplication.html">QApplication</a> object, while other tablet events are sendt to the <a href="qwidget.html">QWidget</a>'s <tt>event()</tt>, which sends them on to <a href="qwidget.html#tabletEvent">tabletEvent()</a>. Since we want to handle these events we have implemented <tt>TabletApplication</tt>.</p>
<a name="tabletapplication-class-implementation"></a>
<h2>TabletApplication Class Implementation</h2>
<p>Here is the implementation of <tt>event()</tt>:</p>
<pre class="cpp"> <span class="type">bool</span> TabletApplication<span class="operator">::</span>event(<span class="type"><a href="qevent.html">QEvent</a></span> <span class="operator">*</span>event)
 {
     <span class="keyword">if</span> (event<span class="operator">-</span><span class="operator">&gt;</span>type() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>TabletEnterProximity <span class="operator">|</span><span class="operator">|</span>
         event<span class="operator">-</span><span class="operator">&gt;</span>type() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>TabletLeaveProximity) {
         myCanvas<span class="operator">-</span><span class="operator">&gt;</span>setTabletDevice(
             <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qtabletevent.html">QTabletEvent</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(event)<span class="operator">-</span><span class="operator">&gt;</span>device());
         <span class="keyword">return</span> <span class="keyword">true</span>;
     }
     <span class="keyword">return</span> <span class="type"><a href="qapplication.html">QApplication</a></span><span class="operator">::</span>event(event);
 }</pre>
<p>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 <tt>setTabletDevice()</tt> in <tt>TabletCanvas</tt>.</p>
<a name="the-function"></a>
<h2>The <tt>main()</tt> function</h2>
<p>Here is the examples <tt>main()</tt> function:</p>
<pre class="cpp"> <span class="type">int</span> main(<span class="type">int</span> argv<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>args<span class="operator">[</span><span class="operator">]</span>)
 {
     TabletApplication app(argv<span class="operator">,</span> args);
     TabletCanvas <span class="operator">*</span>canvas <span class="operator">=</span> <span class="keyword">new</span> TabletCanvas;
     app<span class="operator">.</span>setCanvas(canvas);

     MainWindow mainWindow(canvas);
 <span class="preprocessor">#if defined(Q_OS_SYMBIAN)</span>
     mainWindow<span class="operator">.</span>showMaximized();
 <span class="preprocessor">#elif defined(Q_WS_MAEMO_5) || defined(Q_WS_SIMULATOR)</span>
     mainWindow<span class="operator">.</span>show();
 <span class="preprocessor">#else</span>
     mainWindow<span class="operator">.</span>resize(<span class="number">500</span><span class="operator">,</span> <span class="number">500</span>);
     mainWindow<span class="operator">.</span>show();
 <span class="preprocessor">#endif</span>
     <span class="keyword">return</span> app<span class="operator">.</span>exec();
 }</pre>
<p>In the <tt>main()</tt> function we create a <tt>MainWinow</tt> and display it as a top level window. We use the <tt>TabletApplication</tt> class. We need to set the canvas after the application is created. We cannot use classes that implement event handling before an <a href="qapplication.html">QApplication</a> object is instantiated.</p>
</div>
<!-- @@@widgets/tablet -->
      </div>
    </div>
    </div> 
    <div class="ft">
      <span></span>
    </div>
  </div> 
  <div class="footer">
    <p>
      <acronym title="Copyright">&copy;</acronym> 2013 Digia Plc and/or its
      subsidiaries. Documentation contributions included herein are the copyrights of
      their respective owners.</p>
    <br />
    <p>
      The documentation provided herein is licensed under the terms of the
      <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation
      License version 1.3</a> as published by the Free Software Foundation.</p>
    <p>
      Documentation sources may be obtained from <a href="http://www.qt-project.org">
      www.qt-project.org</a>.</p>
    <br />
    <p>
      Digia, Qt and their respective logos are trademarks of Digia Plc 
      in Finland and/or other countries worldwide. All other trademarks are property
      of their respective owners. <a title="Privacy Policy"
      href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
  </div>

  <script src="scripts/functions.js" type="text/javascript"></script>
</body>
</html>