Sophie

Sophie

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

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" />
<!-- overpainting.qdoc -->
  <title>Qt 4.8: Overpainting 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>Overpainting 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="#glwidget-class-definition">GLWidget Class Definition</a></li>
<li class="level1"><a href="#glwidget-class-implementation">GLWidget Class Implementation</a></li>
<li class="level1"><a href="#summary">Summary</a></li>
</ul>
</div>
<h1 class="title">Overpainting Example</h1>
<span class="subtitle"></span>
<!-- $$$opengl/overpainting-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="opengl-overpainting-bubble-cpp.html">opengl/overpainting/bubble.cpp</a></li>
<li><a href="opengl-overpainting-bubble-h.html">opengl/overpainting/bubble.h</a></li>
<li><a href="opengl-overpainting-glwidget-cpp.html">opengl/overpainting/glwidget.cpp</a></li>
<li><a href="opengl-overpainting-glwidget-h.html">opengl/overpainting/glwidget.h</a></li>
<li><a href="opengl-overpainting-main-cpp.html">opengl/overpainting/main.cpp</a></li>
<li><a href="opengl-overpainting-overpainting-pro.html">opengl/overpainting/overpainting.pro</a></li>
</ul>
<p>The Overpainting example shows how <a href="qpainter.html">QPainter</a> can be used to overpaint a scene rendered using OpenGL in a <a href="qglwidget.html">QGLWidget</a>.<p class="centerAlign"><img src="images/overpainting-example.png" alt="" /></p><p><a href="qglwidget.html">QGLWidget</a> provides a widget with integrated OpenGL graphics support that enables 3D graphics to be displayed using normal OpenGL calls, yet also behaves like any other standard Qt widget with support for signals and slots, properties, and Qt's action system.</p>
<p>Usually, <a href="qglwidget.html">QGLWidget</a> is subclassed to display a pure 3D scene. The developer reimplements <a href="qglwidget.html#initializeGL">initializeGL()</a> to initialize any required resources, <a href="qglwidget.html#resizeGL">resizeGL()</a> to set up the projection and viewport, and <a href="qglwidget.html#paintGL">paintGL()</a> to perform the OpenGL calls needed to render the scene. However, it is possible to subclass <a href="qglwidget.html">QGLWidget</a> differently to allow 2D graphics, drawn using <a href="qpainter.html">QPainter</a>, to be painted over a scene rendered using OpenGL.</p>
<p>In this example, we demonstrate how this is done by reusing the code from the <a href="opengl-hellogl.html">Hello GL</a> example to provide a 3D scene, and painting over it with some translucent 2D graphics. Instead of examining each class in detail, we only cover the parts of the <tt>GLWidget</tt> class that enable overpainting, and provide more detailed discussion in the final section of this document.</p>
<a name="glwidget-class-definition"></a>
<h2>GLWidget Class Definition</h2>
<p>The <tt>GLWidget</tt> class is a subclass of <a href="qglwidget.html">QGLWidget</a>, based on the one used in the <a href="opengl-hellogl.html">Hello GL</a> example. Rather than describe the class as a whole, we show the first few lines of the class and only discuss the changes we have made to the rest of it:</p>
<pre class="cpp"> <span class="keyword">class</span> GLWidget : <span class="keyword">public</span> <span class="type"><a href="qglwidget.html">QGLWidget</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     GLWidget(<span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);
     <span class="operator">~</span>GLWidget();
     ...
 <span class="keyword">protected</span>:
     <span class="type">void</span> initializeGL();
     <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> resizeGL(<span class="type">int</span> width<span class="operator">,</span> <span class="type">int</span> height);
     <span class="type">void</span> mousePressEvent(<span class="type"><a href="qmouseevent.html">QMouseEvent</a></span> <span class="operator">*</span>event);
     <span class="type">void</span> mouseMoveEvent(<span class="type"><a href="qmouseevent.html">QMouseEvent</a></span> <span class="operator">*</span>event);
     <span class="type">void</span> showEvent(<span class="type"><a href="qshowevent.html">QShowEvent</a></span> <span class="operator">*</span>event);

 <span class="keyword">private</span> <span class="keyword">slots</span>:
     <span class="type">void</span> animate();

 <span class="keyword">private</span>:
     <span class="type">void</span> createBubbles(<span class="type">int</span> number);
     <span class="type">void</span> drawInstructions(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">*</span>painter);
     ...
     <span class="type">QtLogo</span> <span class="operator">*</span>logo;
     <span class="type"><a href="qlist.html">QList</a></span><span class="operator">&lt;</span>Bubble<span class="operator">*</span><span class="operator">&gt;</span> bubbles;
     <span class="type"><a href="qtimer.html">QTimer</a></span> animationTimer;</pre>
<p>As usual, the widget uses <a href="qglwidget.html#initializeGL">initializeGL()</a> to set up geometry for our scene and perform OpenGL initialization tasks. The <a href="qglwidget.html#resizeGL">resizeGL()</a> function is used to ensure that the 3D graphics in the scene are transformed correctly to the 2D viewport displayed in the widget.</p>
<p>Instead of implementing <a href="qglwidget.html#paintGL">paintGL()</a> to handle updates to the widget, we implement a normal <a href="qwidget.html#paintEvent">QWidget::paintEvent</a>(). This allows us to mix OpenGL calls and <a href="qpainter.html">QPainter</a> operations in a controlled way.</p>
<p>In this example, we also implement <a href="qwidget.html#showEvent">QWidget::showEvent</a>() to help with the initialization of the 2D graphics used.</p>
<p>The new private member functions and variables relate exclusively to the 2D graphics and animation. The <tt>animate()</tt> slot is called periodically by the <tt>animationTimer</tt> to update the widget; the <tt>createBubbles()</tt> function initializes the <tt>bubbles</tt> list with instances of a helper class used to draw the animation; the <tt>drawInstructions()</tt> function is responsible for a semi-transparent message that is also overpainted onto the OpenGL scene.</p>
<a name="glwidget-class-implementation"></a>
<h2>GLWidget Class Implementation</h2>
<p>Again, we only show the parts of the <tt>GLWidget</tt> implementation that are relevant to this example. In the constructor, we initialize a <a href="qtimer.html">QTimer</a> to control the animation:</p>
<pre class="cpp"> GLWidget<span class="operator">::</span>GLWidget(<span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent)
     : <span class="type"><a href="qglwidget.html">QGLWidget</a></span>(<span class="type"><a href="qglformat.html">QGLFormat</a></span>(QGL<span class="operator">::</span>SampleBuffers)<span class="operator">,</span> parent)
 {
     <span class="type"><a href="qtime.html">QTime</a></span> midnight(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>);
     qsrand(midnight<span class="operator">.</span>secsTo(<span class="type"><a href="qtime.html">QTime</a></span><span class="operator">::</span>currentTime()));

     logo <span class="operator">=</span> <span class="number">0</span>;
     xRot <span class="operator">=</span> <span class="number">0</span>;
     yRot <span class="operator">=</span> <span class="number">0</span>;
     zRot <span class="operator">=</span> <span class="number">0</span>;

     qtGreen <span class="operator">=</span> <span class="type"><a href="qcolor.html">QColor</a></span><span class="operator">::</span>fromCmykF(<span class="number">0.40</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">1.0</span><span class="operator">,</span> <span class="number">0.0</span>);
     qtPurple <span class="operator">=</span> <span class="type"><a href="qcolor.html">QColor</a></span><span class="operator">::</span>fromCmykF(<span class="number">0.39</span><span class="operator">,</span> <span class="number">0.39</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">0.0</span>);

     animationTimer<span class="operator">.</span>setSingleShot(<span class="keyword">false</span>);
     connect(<span class="operator">&amp;</span>animationTimer<span class="operator">,</span> SIGNAL(timeout())<span class="operator">,</span> <span class="keyword">this</span><span class="operator">,</span> SLOT(animate()));
     animationTimer<span class="operator">.</span>start(<span class="number">25</span>);

     setAutoFillBackground(<span class="keyword">false</span>);
     setMinimumSize(<span class="number">200</span><span class="operator">,</span> <span class="number">200</span>);
     setWindowTitle(tr(<span class="string">&quot;Overpainting a Scene&quot;</span>));
 }</pre>
<p>We turn off the widget's <a href="qwidget.html#autoFillBackground-prop">autoFillBackground</a> property to instruct OpenGL not to paint a background for the widget when <a href="qpainter.html#begin">QPainter::begin()</a> is called.</p>
<p>As in the <a href="opengl-hellogl.html">Hello GL</a> example, the destructor is responsible for freeing any OpenGL-related resources:</p>
<pre class="cpp"> GLWidget<span class="operator">::</span><span class="operator">~</span>GLWidget()
 {
 }</pre>
<p>The <tt>initializeGL()</tt> function is fairly minimal, only setting up the QtLogo object used in the scene. See the <a href="opengl-hellogl.html">Hello GL</a> example for details of the QtLogo class.</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>initializeGL()
 {
     glEnable(GL_MULTISAMPLE);

     logo <span class="operator">=</span> <span class="keyword">new</span> <span class="type">QtLogo</span>(<span class="keyword">this</span>);
     logo<span class="operator">-</span><span class="operator">&gt;</span>setColor(qtGreen<span class="operator">.</span>dark());
 }</pre>
<p>To cooperate fully with <a href="qpainter.html">QPainter</a>, we defer matrix stack operations and attribute initialization until the widget needs to be updated.</p>
<p>In this example, we implement <a href="qwidget.html#paintEvent">paintEvent()</a> rather than <a href="qglwidget.html#paintGL">paintGL()</a> to render our scene. When drawing on a <a href="qglwidget.html">QGLWidget</a>, the paint engine used by <a href="qpainter.html">QPainter</a> performs certain operations that change the states of the OpenGL implementation's matrix and property stacks. Therefore, it is necessary to make all the OpenGL calls to display the 3D graphics before we construct a <a href="qpainter.html">QPainter</a> to draw the 2D overlay.</p>
<p>We render a 3D scene by setting up model and projection transformations and other attributes. We use an OpenGL stack operation to preserve the original matrix state, allowing us to recover it later:</p>
<pre class="cpp">     glMatrixMode(GL_MODELVIEW);
     glPushMatrix();</pre>
<p>We define a color to use for the widget's background, and set up various attributes that define how the scene will be rendered.</p>
<pre class="cpp">     qglClearColor(qtPurple<span class="operator">.</span>dark());
     glShadeModel(GL_SMOOTH);
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_CULL_FACE);
     glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
     glEnable(GL_MULTISAMPLE);
     <span class="keyword">static</span> GLfloat lightPosition<span class="operator">[</span><span class="number">4</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">0.5</span><span class="operator">,</span> <span class="number">5.0</span><span class="operator">,</span> <span class="number">7.0</span><span class="operator">,</span> <span class="number">1.0</span> };
     glLightfv(GL_LIGHT0<span class="operator">,</span> GL_POSITION<span class="operator">,</span> lightPosition);

     setupViewport(width()<span class="operator">,</span> height());</pre>
<p>We call the <tt>setupViewport()</tt> private function to set up the projection used for the scene. This is unnecessary in OpenGL examples that implement the <a href="qglwidget.html#paintGL">paintGL()</a> function because the matrix stacks are usually unmodified between calls to <a href="qglwidget.html#resizeGL">resizeGL()</a> and <a href="qglwidget.html#paintGL">paintGL()</a>.</p>
<p>Since the widget's background is not drawn by the system or by Qt, we use an OpenGL call to paint it before positioning the object defined earlier in the scene:</p>
<pre class="cpp">     glClear(GL_COLOR_BUFFER_BIT <span class="operator">|</span> GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
     glTranslatef(<span class="number">0.0</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="operator">-</span><span class="number">10.0</span>);
     glRotatef(xRot <span class="operator">/</span> <span class="number">16.0</span><span class="operator">,</span> <span class="number">1.0</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">0.0</span>);
     glRotatef(yRot <span class="operator">/</span> <span class="number">16.0</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">1.0</span><span class="operator">,</span> <span class="number">0.0</span>);
     glRotatef(zRot <span class="operator">/</span> <span class="number">16.0</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">0.0</span><span class="operator">,</span> <span class="number">1.0</span>);

     logo<span class="operator">-</span><span class="operator">&gt;</span>draw();</pre>
<p>Once the QtLogo object's draw method has been executed, the GL states we changed and the matrix stack needs to be restored to its original state at the start of this function before we can begin overpainting:</p>
<pre class="cpp">     glShadeModel(GL_FLAT);
     glDisable(GL_CULL_FACE);
     glDisable(GL_DEPTH_TEST);
     glDisable(GL_LIGHTING);

     glMatrixMode(GL_MODELVIEW);
     glPopMatrix();</pre>
<p>With the 3D graphics done, we construct a <a href="qpainter.html">QPainter</a> for use on the widget and simply overpaint the widget with 2D graphics; in this case, using a helper class to draw a number of translucent bubbles onto the widget, and calling <tt>drawInstructions()</tt> to overlay some instructions:</p>
<pre class="cpp">     <span class="type"><a href="qpainter.html">QPainter</a></span> painter(<span class="keyword">this</span>);
     painter<span class="operator">.</span>setRenderHint(<span class="type"><a href="qpainter.html">QPainter</a></span><span class="operator">::</span>Antialiasing);
     foreach (Bubble <span class="operator">*</span>bubble<span class="operator">,</span> bubbles) {
         <span class="keyword">if</span> (bubble<span class="operator">-</span><span class="operator">&gt;</span>rect()<span class="operator">.</span>intersects(event<span class="operator">-</span><span class="operator">&gt;</span>rect()))
             bubble<span class="operator">-</span><span class="operator">&gt;</span>drawBubble(<span class="operator">&amp;</span>painter);
     }
     drawInstructions(<span class="operator">&amp;</span>painter);
     painter<span class="operator">.</span>end();
 }</pre>
<p>When <a href="qpainter.html#end">QPainter::end</a>() is called, suitable OpenGL-specific calls are made to write the scene, and its additional contents, onto the widget.</p>
<p>With <a href="qglwidget.html#paintGL">paintGL()</a> the <a href="qglwidget.html#swapBuffers">swapBuffers()</a> call is done for us. But an explicit call to swapBuffers() is still not required because in the <a href="qwidget.html#paintEvent">paintEvent()</a> method the <a href="qpainter.html">QPainter</a> on the OpenGL widget takes care of this for us.</p>
<p>The implementation of the <a href="qglwidget.html#resizeGL">resizeGL()</a> function sets up the dimensions of the viewport and defines a projection transformation:</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>resizeGL(<span class="type">int</span> width<span class="operator">,</span> <span class="type">int</span> height)
 {
     setupViewport(width<span class="operator">,</span> height);
 }</pre>
<p>Ideally, we want to arrange the 2D graphics to suit the widget's dimensions. To achieve this, we implement the <a href="qwidget.html#showEvent">showEvent()</a> handler, creating new graphic elements (bubbles) if necessary at appropriate positions in the widget.</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>showEvent(<span class="type"><a href="qshowevent.html">QShowEvent</a></span> <span class="operator">*</span>event)
 {
     Q_UNUSED(event);
     createBubbles(<span class="number">20</span> <span class="operator">-</span> bubbles<span class="operator">.</span>count());
 }</pre>
<p>This function only has an effect if less than 20 bubbles have already been created.</p>
<p>The <tt>animate()</tt> slot is called every time the widget's <tt>animationTimer</tt> emits the <a href="qtimer.html#timeout">timeout()</a> signal. This keeps the bubbles moving around.</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>animate()
 {
     <span class="type"><a href="qmutablelistiterator.html">QMutableListIterator</a></span><span class="operator">&lt;</span>Bubble<span class="operator">*</span><span class="operator">&gt;</span> iter(bubbles);

     <span class="keyword">while</span> (iter<span class="operator">.</span>hasNext()) {
         Bubble <span class="operator">*</span>bubble <span class="operator">=</span> iter<span class="operator">.</span>next();
         bubble<span class="operator">-</span><span class="operator">&gt;</span>move(rect());
     }
     update();
 }</pre>
<p>We simply iterate over the bubbles in the <tt>bubbles</tt> list, updating the widget before and after each of them is moved.</p>
<p>The <tt>setupViewport()</tt> function is called from <tt>paintEvent()</tt> and <tt>resizeGL()</tt>.</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>setupViewport(<span class="type">int</span> width<span class="operator">,</span> <span class="type">int</span> height)
 {
     <span class="type">int</span> side <span class="operator">=</span> <a href="qtglobal.html#qMin">qMin</a>(width<span class="operator">,</span> height);
     glViewport((width <span class="operator">-</span> side) <span class="operator">/</span> <span class="number">2</span><span class="operator">,</span> (height <span class="operator">-</span> side) <span class="operator">/</span> <span class="number">2</span><span class="operator">,</span> side<span class="operator">,</span> side);

     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
 <span class="preprocessor">#ifdef QT_OPENGL_ES</span>
     glOrthof(<span class="operator">-</span><span class="number">0.5</span><span class="operator">,</span> <span class="operator">+</span><span class="number">0.5</span><span class="operator">,</span> <span class="operator">-</span><span class="number">0.5</span><span class="operator">,</span> <span class="number">0.5</span><span class="operator">,</span> <span class="number">4.0</span><span class="operator">,</span> <span class="number">15.0</span>);
 <span class="preprocessor">#else</span>
     glOrtho(<span class="operator">-</span><span class="number">0.5</span><span class="operator">,</span> <span class="operator">+</span><span class="number">0.5</span><span class="operator">,</span> <span class="operator">-</span><span class="number">0.5</span><span class="operator">,</span> <span class="number">0.5</span><span class="operator">,</span> <span class="number">4.0</span><span class="operator">,</span> <span class="number">15.0</span>);
 <span class="preprocessor">#endif</span>
     glMatrixMode(GL_MODELVIEW);
 }</pre>
<p>The <tt>drawInstructions()</tt> function is used to prepare some basic instructions that will be painted with the other 2D graphics over the 3D scene.</p>
<pre class="cpp"> <span class="type">void</span> GLWidget<span class="operator">::</span>drawInstructions(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">*</span>painter)
 {
     <span class="type"><a href="qstring.html">QString</a></span> text <span class="operator">=</span> tr(<span class="string">&quot;Click and drag with the left mouse button &quot;</span>
                       <span class="string">&quot;to rotate the Qt logo.&quot;</span>);
     <span class="type"><a href="qfontmetrics.html">QFontMetrics</a></span> metrics <span class="operator">=</span> <span class="type"><a href="qfontmetrics.html">QFontMetrics</a></span>(font());
     <span class="type">int</span> border <span class="operator">=</span> <a href="qtglobal.html#qMax">qMax</a>(<span class="number">4</span><span class="operator">,</span> metrics<span class="operator">.</span>leading());

     <span class="type"><a href="qrect.html">QRect</a></span> rect <span class="operator">=</span> metrics<span class="operator">.</span>boundingRect(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width() <span class="operator">-</span> <span class="number">2</span><span class="operator">*</span>border<span class="operator">,</span> <span class="type">int</span>(height()<span class="operator">*</span><span class="number">0.125</span>)<span class="operator">,</span>
                                       <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>AlignCenter <span class="operator">|</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>TextWordWrap<span class="operator">,</span> text);
     painter<span class="operator">-</span><span class="operator">&gt;</span>setRenderHint(<span class="type"><a href="qpainter.html">QPainter</a></span><span class="operator">::</span>TextAntialiasing);
     painter<span class="operator">-</span><span class="operator">&gt;</span>fillRect(<span class="type"><a href="qrect.html">QRect</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width()<span class="operator">,</span> rect<span class="operator">.</span>height() <span class="operator">+</span> <span class="number">2</span><span class="operator">*</span>border)<span class="operator">,</span>
                      <span class="type"><a href="qcolor.html">QColor</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">127</span>));
     painter<span class="operator">-</span><span class="operator">&gt;</span>setPen(<span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>white);
     painter<span class="operator">-</span><span class="operator">&gt;</span>fillRect(<span class="type"><a href="qrect.html">QRect</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width()<span class="operator">,</span> rect<span class="operator">.</span>height() <span class="operator">+</span> <span class="number">2</span><span class="operator">*</span>border)<span class="operator">,</span>
                       <span class="type"><a href="qcolor.html">QColor</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">127</span>));
     painter<span class="operator">-</span><span class="operator">&gt;</span>drawText((width() <span class="operator">-</span> rect<span class="operator">.</span>width())<span class="operator">/</span><span class="number">2</span><span class="operator">,</span> border<span class="operator">,</span>
                       rect<span class="operator">.</span>width()<span class="operator">,</span> rect<span class="operator">.</span>height()<span class="operator">,</span>
                       <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>AlignCenter <span class="operator">|</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>TextWordWrap<span class="operator">,</span> text);
 }</pre>
<a name="summary"></a>
<h2>Summary</h2>
<p>When overpainting 2D content onto 3D content, we need to use a <a href="qpainter.html">QPainter</a> <i>and</i> make OpenGL calls to achieve the desired effect. Since <a href="qpainter.html">QPainter</a> itself uses OpenGL calls when used on a <a href="qglwidget.html">QGLWidget</a> subclass, we need to preserve the state of various OpenGL stacks when we perform our own calls, using the following approach:</p>
<ul>
<li>Reimplement <a href="qglwidget.html#initializeGL">QGLWidget::initializeGL</a>(), but only perform minimal initialization. <a href="qpainter.html">QPainter</a> will perform its own initialization routines, modifying the matrix and property stacks, so it is better to defer certain initialization tasks until just before you render the 3D scene.</li>
<li>Reimplement <a href="qglwidget.html#resizeGL">QGLWidget::resizeGL</a>() as in the pure 3D case.</li>
<li>Reimplement <a href="qwidget.html#paintEvent">QWidget::paintEvent</a>() to draw both 2D and 3D graphics.</li>
</ul>
<p>The <a href="qwidget.html#paintEvent">paintEvent()</a> implementation performs the following tasks:</p>
<ul>
<li>Push the current OpenGL modelview matrix onto a stack.</li>
<li>Perform initialization tasks usually done in the <a href="qglwidget.html#initializeGL">initializeGL()</a> function.</li>
<li>Perform code that would normally be located in the widget's <a href="qglwidget.html#resizeGL">resizeGL()</a> function to set the correct perspective transformation and set up the viewport.</li>
<li>Render the scene using OpenGL calls.</li>
<li>Pop the OpenGL modelview matrix off the stack.</li>
<li>Construct a <a href="qpainter.html">QPainter</a> object.</li>
<li>Initialize it for use on the widget with the <a href="qpainter.html#begin">QPainter::begin</a>() function.</li>
<li>Draw primitives using <a href="qpainter.html">QPainter</a>'s member functions.</li>
<li>Call <a href="qpainter.html#end">QPainter::end</a>() to finish painting.</li>
</ul>
</div>
<!-- @@@opengl/overpainting -->
      </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>