C.9. Chapter 9

C.9.1. Exercises

C.9.1.1. What if the process of creating your window contents is a long job? Combine the QTimer method for long jobs with double-buffering to efficiently paint a complex scene without hanging the GUI. Your program's GUI should still respond to input while the application is painting the window. (You can easily check this by attempting to close the window while the program is painting.)

C.9.1.1. What if the process of creating your window contents is a long job? Combine the QTimer method for long jobs with double-buffering to efficiently paint a complex scene without hanging the GUI. Your program's GUI should still respond to input while the application is painting the window. (You can easily check this by attempting to close the window while the program is painting.)

Listings C.28–C.30 give possible answers to Exercise 1.


Example C.28. klongdraw.h: Class Declaration for KLongDraw, a Widget That Draws a Complex Scene

   1 
   2 #ifndef __KQUICKDRAW_H__
   3 #define __KQUICKDRAW_H__
   4 
   5 
   6 #include <qwidget.h>
   7 
   8 class QPixmap;
   9 class QTimer;
  10 
  11 const int NEllipses=50000;
  12 
  13 /**
  14  * KLongDraw
  15  * Handle long drawing job while keeping UI alive.
  16  **/
  17 class KLongDraw : public QWidget
  18 {
  19  Q_OBJECT
  20 
  21  public:
  22   KLongDraw (QWidget *parent, const char *name=0);
  23 
  24   protected slots:
  25     /**
  26      * Redraw some of the scene then exit and check the UI.
  27      **/
  28     void slotDrawSome();
  29 
  30  protected:
  31   /**
  32    * Repaint the window using a bit-block transfer from the
  33    *  off-screen buffer (a QPixmap).  Recreate the pixmap first,
  34    *  if necessary.
  35    **/
  36   void paintEvent (QPaintEvent *);
  37 
  38   void resizeEvent (QResizeEvent *);
  39  private:
  40   QTimer *qtimer;
  41   QPixmap *qpixmap;
  42   bool bneedrecreate;
  43   double x[NEllipses], y[NEllipses];
  44   int w, h;
  45   int total;
  46 };
  47 
  48 #endif
  49 


Example C.29. klongdraw.cpp: Class Definition for KLongDraw, a Widget That Draws a Complex Scene

   1 
   2 #include <qpainter.h>
   3 #include <qtimer.h>
   4 #include <qpixmap.h>
   5 
   6 #include <kmenubar.h>
   7 #include <kapp.h>
   8 #include <kstdaccel.h>
   9 
  10 #include "klongdraw.moc"
  11 
  12 
  13 KLongDraw::KLongDraw (QWidget *parent, const char *name=0) :
  14   QWidget (parent, name)
  15 {
  16   bneedrecreate=true;
  17   qpixmap=0;
  18 
  19   for (int i=0; i<NEllipses; i++)
  20     {
  21       x[i]=(kapp->random()%1000)/1000.;
  22       y[i]=(kapp->random()%1000)/1000.;
  23     }
  24 
  25   setBackgroundMode (NoBackground);
  26 
  27   qtimer = new QTimer (this);
  28   connect ( qtimer, SIGNAL (timeout()),
  29             this, SLOT (slotDrawSome()) );
  30 }
  31 void
  32 KLongDraw::paintEvent (QPaintEvent *)
  33 {
  34 
  35   if (bneedrecreate)
  36     {
  37       if (qpixmap!=0)
  38         delete qpixmap;
  39       qpixmap = new QPixmap (width(), height());
  40 
  41       QPainter qpainter;
  42       qpainter.begin (qpixmap, this);
  43       qpainter.fillRect (qpixmap->rect(), white);
  44 
  45       bitBlt (this, 0, 0, qpixmap);
  46 
  47       w = width()/100;
  48       h = height()/100;
  49 
  50       bneedrecreate=false;
  51       total=0;
  52 
  53       qtimer->start(0);
  54     }
  55 
  56   bitBlt (this, 0, 0, qpixmap);
  57 
  58 }
  59 
  60 void
  61 KLongDraw::slotDrawSome()
  62 {
  63 
  64   QPainter qpainter;
  65   qpainter.begin (qpixmap, this);
  66 
  67   qpainter.setBrush (blue);
  68 
  69   int imax = total+100;
  70   for (int i=total; i<imax; i++)
  71     qpainter.drawEllipse (x[i]*width(), y[i]*height(), w, h);
  72   total = imax;
  73   //This updates the window periodically with the partially-drawn scene.
  74   // While this _does_ indicate progress on the update, you might,
  75   // instead, update a progress bar here and only call update()
  76   // after the entire scene has been drawn.
  77   if (!(total%1000))
  78     update();
  79 
  80   if (total>=NEllipses)
  81     {
  82       qtimer->stop();
  83       update();
  84     }
  85 
  86 
  87 }
  88 void
  89 KLongDraw::resizeEvent (QResizeEvent *)
  90 {
  91   bneedrecreate = true;
  92 }
  93 


Example C.30. main.cpp: A main() Function Suitable for Testing KLongDraw

   1 
   2 #include <kapp.h>
   3 
   4 #include "klongdraw.h"
   5 
   6 int
   7 main (int argc, char *argv[])
   8 {
   9   KApplication kapplication  (argc, argv, "klongdrawtest");
  10   KLongDraw *klongdraw = new KLongDraw (0);
  11 
  12   kapplication.setMainWidget (klongdraw);
  13 
  14   klongdraw->show();
  15   return kapplication.exec();
  16 }
  17