Progress Bar and Dialog Example
This example displays either a simple (text-only) or a
custom-labelled (user-supplied widget) progress dialog. It also
demonstrates simple use of menus.
Implementation:
/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
**
** This file is part of an example program for Qt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
#include <qprogressdialog.h>
#include <qapplication.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qpainter.h>
#include <stdlib.h>
class AnimatedThingy : public QLabel {
public:
AnimatedThingy( QWidget* parent, const QString& s ) :
QLabel(parent),
label(s),
step(0)
{
label+="\n... and wasting CPU\nwith this animation!\n";
for (int i=0; i<nqix; i++)
ox[0][i] = oy[0][i] = ox[1][i] = oy[1][i] = 0;
x0 = y0 = x1 = y1 = 0;
dx0 = rand()%8+2;
dy0 = rand()%8+2;
dx1 = rand()%8+2;
dy1 = rand()%8+2;
}
void show()
{
if (!isVisible()) startTimer(100);
QWidget::show();
}
void hide()
{
QWidget::hide();
killTimers();
}
QSize sizeHint() const
{
return QSize(120,100);
}
protected:
void timerEvent(QTimerEvent*)
{
QPainter p(this);
QPen pn=p.pen();
pn.setWidth(2);
pn.setColor(backgroundColor());
p.setPen(pn);
step = (step + 1) % nqix;
p.drawLine(ox[0][step], oy[0][step], ox[1][step], oy[1][step]);
inc(x0, dx0, width());
inc(y0, dy0, height());
inc(x1, dx1, width());
inc(y1, dy1, height());
ox[0][step] = x0;
oy[0][step] = y0;
ox[1][step] = x1;
oy[1][step] = y1;
QColor c;
c.setHsv( (step*255)/nqix, 255, 255 ); // rainbow effect
pn.setColor(c);
p.setPen(pn);
p.drawLine(ox[0][step], oy[0][step], ox[1][step], oy[1][step]);
p.setPen(colorGroup().text());
p.drawText(rect(), AlignCenter, label);
}
void paintEvent(QPaintEvent* event)
{
QPainter p(this);
QPen pn=p.pen();
pn.setWidth(2);
p.setPen(pn);
p.setClipRect(event->rect());
for (int i=0; i<nqix; i++) {
QColor c;
c.setHsv( (i*255)/nqix, 255, 255 ); // rainbow effect
pn.setColor(c);
p.setPen(pn);
p.drawLine(ox[0][i], oy[0][i], ox[1][i], oy[1][i]);
}
p.setPen(colorGroup().text());
p.drawText(rect(), AlignCenter, label);
}
private:
void inc(int& x, int& dx, int b)
{
x+=dx;
if (x<0) { x=0; dx=rand()%8+2; }
else if (x>=b) { x=b-1; dx=-(rand()%8+2); }
}
enum {nqix=10};
int ox[2][nqix];
int oy[2][nqix];
int x0,y0,x1,y1;
int dx0,dy0,dx1,dy1;
QString label;
int step;
};
class CPUWaster : public QWidget
{
Q_OBJECT
enum { first_draw_item = 1000, last_draw_item = 1006 };
int drawItemRects(int id)
{
int n = id - first_draw_item;
int r = 100;
while (n--) r*=(n%3 ? 5 : 4);
return r;
}
QString drawItemText(int id)
{
QString str;
str.sprintf("%d Rectangles", drawItemRects(id));
return str;
}
public:
CPUWaster() :
pb(0)
{
menubar = new QMenuBar( this, "menu" );
Q_CHECK_PTR( menubar );
QPopupMenu* file = new QPopupMenu();
Q_CHECK_PTR( file );
menubar->insertItem( "&File", file );
for (int i=first_draw_item; i<=last_draw_item; i++)
file->insertItem( drawItemText(i), i );
connect( menubar, SIGNAL(activated(int)), this, SLOT(doMenuItem(int)) );
file->insertSeparator();
file->insertItem( "Quit", qApp, SLOT(quit()) );
options = new QPopupMenu();
Q_CHECK_PTR( options );
menubar->insertItem( "&Options", options );
td_id = options->insertItem( "Timer driven", this, SLOT(timerDriven()) );
ld_id = options->insertItem( "Loop driven", this, SLOT(loopDriven()) );
options->insertSeparator();
dl_id = options->insertItem( "Default label", this, SLOT(defaultLabel()) );
cl_id = options->insertItem( "Custom label", this, SLOT(customLabel()) );
options->insertSeparator();
md_id = options->insertItem( "No minimum duration", this, SLOT(toggleMinimumDuration()) );
options->setCheckable( TRUE );
loopDriven();
defaultLabel();
setFixedSize( 400, 300 );
setBackgroundColor( black );
}
public slots:
void doMenuItem(int id)
{
if (id >= first_draw_item && id <= last_draw_item)
draw(drawItemRects(id));
}
void stopDrawing() { got_stop = TRUE; }
void timerDriven()
{
timer_driven = TRUE;
options->setItemChecked( td_id, TRUE );
options->setItemChecked( ld_id, FALSE );
}
void loopDriven()
{
timer_driven = FALSE;
options->setItemChecked( ld_id, TRUE );
options->setItemChecked( td_id, FALSE );
}
void defaultLabel()
{
default_label = TRUE;
options->setItemChecked( dl_id, TRUE );
options->setItemChecked( cl_id, FALSE );
}
void customLabel()
{
default_label = FALSE;
options->setItemChecked( dl_id, FALSE );
options->setItemChecked( cl_id, TRUE );
}
void toggleMinimumDuration()
{
options->setItemChecked( md_id,
!options->isItemChecked( md_id ) );
}
private:
void timerEvent( QTimerEvent* )
{
if (!got_stop)
pb->setProgress( pb->totalSteps() - rects );
rects--;
{
QPainter p(this);
int ww = width();
int wh = height();
if ( ww > 8 && wh > 8 ) {
QColor c(rand()%255, rand()%255, rand()%255);
int x = rand() % (ww-8);
int y = rand() % (wh-8);
int w = rand() % (ww-x);
int h = rand() % (wh-y);
p.fillRect( x, y, w, h, c );
}
}
if (!rects || got_stop) {
if (!got_stop)
pb->setProgress( pb->totalSteps() );
QPainter p(this);
p.fillRect(0, 0, width(), height(), backgroundColor());
enableDrawingItems(TRUE);
killTimers();
delete pb;
pb = 0;
}
}
QProgressDialog* newProgressDialog( const char* label, int steps, bool modal )
{
QProgressDialog *d = new QProgressDialog(label, "Cancel", steps, this,
"progress", modal);
if ( options->isItemChecked( md_id ) )
d->setMinimumDuration(0);
if ( !default_label )
d->setLabel( new AnimatedThingy(d,label) );
return d;
}
void enableDrawingItems(bool yes)
{
for (int i=first_draw_item; i<=last_draw_item; i++) {
menubar->setItemEnabled(i, yes);
}
}
void draw(int n)
{
if ( timer_driven ) {
if ( pb ) {
qWarning("This cannot happen!");
return;
}
rects = n;
pb = newProgressDialog("Drawing rectangles.\n"
"Using timer event.", n, FALSE);
pb->setCaption("Please Wait");
connect(pb, SIGNAL(cancelled()), this, SLOT(stopDrawing()));
enableDrawingItems(FALSE);
startTimer(0);
got_stop = FALSE;
} else {
QProgressDialog* lpb = newProgressDialog(
"Drawing rectangles.\nUsing loop.", n, TRUE);
lpb->setCaption("Please Wait");
QPainter p(this);
for (int i=0; i<n; i++) {
lpb->setProgress(i);
if ( lpb->wasCancelled() )
break;
QColor c(rand()%255, rand()%255, rand()%255);
int x = rand()%(width()-8);
int y = rand()%(height()-8);
int w = rand()%(width()-x);
int h = rand()%(height()-y);
p.fillRect(x,y,w,h,c);
}
p.fillRect(0, 0, width(), height(), backgroundColor());
delete lpb;
}
}
QMenuBar* menubar;
QProgressDialog* pb;
QPopupMenu* options;
int td_id, ld_id;
int dl_id, cl_id;
int md_id;
int rects;
bool timer_driven;
bool default_label;
bool got_stop;
};
int main( int argc, char **argv )
{
QApplication a( argc, argv );
int wincount = argc > 1 ? atoi(argv[1]) : 1;
for ( int i=0; i<wincount; i++ ) {
CPUWaster* cpuw = new CPUWaster;
if ( i == 0 ) a.setMainWidget(cpuw);
cpuw->show();
}
return a.exec();
}
#include "progress.moc"
See also Examples.