Progress Bar

From Qt Wiki
Jump to navigation Jump to search

En Ar Bg De El Es Fa Fi Fr Hi Hu It Ja Kn Ko Ms Nl Pl Pt Ru Sq Th Tr Uk Zh

It is often necessary to display a progress bar while a long operation is happening. The case we are concerned about in this example is when there is no easy way to track the progress of the operation - all that is known is when it is done. There are many ways to do this. You could use a progressBar widget on your widget and run the operation in a different thread (using moveToThread()). This typically requires a special object to be created (a subclass of QObject that runs the operation and then emits a finished() signal), which can be a pain if you need to do this for many different operations.

However, using QFutureWatcher and QtConcurrent::run(), this is extremely easy. Below we demonstrate how to use this technique with both a QProgressDialog and a QProgressBar.

QProgressBar Example

form.h

#ifndef FORM_H
#define FORM_H

#include "ui_form.h"

#include <QFutureWatcher>

#include "MyClass.h"

class Form : public QWidget, private Ui::Form
{
Q_OBJECT

public slots:

void slot_finished();
 void on_pushButton_clicked();

public:
 Form(QWidget *parent = 0);

private:
 QFutureWatcher<void> FutureWatcher;
 MyClass MyObject;
};

#endif

form.cpp

#include <QtGui>
#include <QImage>

#include "form.h"

#include <iostream>

Form::Form(QWidget *parent)
 : QWidget(parent)
{
 setupUi(this);

this->progressBar->setMinimum(0);
 this->progressBar->setMaximum(0);
 this->progressBar->hide();

connect(&this->FutureWatcher, SIGNAL (finished()), this, SLOT (slot_finished()));

}

void Form::slot_finished()
{
 this->progressBar->hide();
}

void Form::on_pushButton_clicked()
{
 this->progressBar->show();

// Start the computation.
 QFuture<void> future = QtConcurrent::run(&this->MyObject, &MyClass::LongFunction);
 this->FutureWatcher.setFuture(future);
}

form.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
 <property name="geometry">
 <rect>
 <x>0</x>
 <y>0</y>
 <width>400</width>
 <height>300</height>
 </rect>
 </property>
 <property name="windowTitle">
 <string>Form</string>
 </property>
 <layout class="QVBoxLayout" name="verticalLayout">
 <item>
 <widget class="QPushButton" name="pushButton">
 <property name="text">
 <string>PushButton</string>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QLineEdit" name="lineEdit"/>
 </item>
 <item>
 <widget class="QProgressBar" name="progressBar">
 <property name="value">
 <number>24</number>
 </property>
 </widget>
 </item>
 </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

FutureWatcher.cpp

#include <QApplication>
#include <QObject>
#include <QThread>

#include <iostream>

#include "form.h"

int main(int argc, char*argv[])
{
 QApplication app(argc, argv);

Form form;

form.show();

return app.exec();
}

MyClass.h

#ifndef MyClass_H
#define MyClass_H

#include <iostream>

class MyClass
{
public:

void LongFunction()
 {
 for( int count = 0; count < 5; count++ )
 {
 sleep( 1 );
 std::cout << "Ping long!" << std::endl;
 }
 }
};

#endif

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

PROJECT (FutureWatcher)

FIND_PACKAGE(Qt4 REQUIRED)
INCLUDE (${QT_USE_FILE})

QT4_WRAP_CPP(MOCSrcs form.h)
QT4_WRAP_UI(UISrcs form.ui)

include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})

ADD_EXECUTABLE(FutureWatcher FutureWatcher.cpp MyClass.cpp form.cpp ${MOCSrcs} ${UISrcs})
TARGET_LINK_LIBRARIES(FutureWatcher ${QT_LIBRARIES})

QProgressDialog Example

form.h

#ifndef FORM_H
#define FORM_H

#include "ui_form.h"

#include <QFutureWatcher>

#include "MyClass.h"

class QProgressDialog;

class Form : public QWidget, private Ui::Form
{
Q_OBJECT

public slots:

void slot_finished();
 void on_pushButton_clicked();

public:
 Form(QWidget '''parent = 0);

private:
 QFutureWatcher<void> FutureWatcher;
 MyClass MyObject;
 QProgressDialog''' ProgressDialog;
};

#endif

form.cpp

#include <QtGui>
#include <QImage>

#include "form.h"

#include <iostream>

Form::Form(QWidget *parent)
 : QWidget(parent)
{
 setupUi(this);

this->ProgressDialog = new QProgressDialog(this);

connect(&this->FutureWatcher, SIGNAL (finished()), this, SLOT (slot_finished()));
 connect(&this->FutureWatcher, SIGNAL (finished()), this->ProgressDialog , SLOT (cancel()));

}

void Form::slot_finished()
{
 std::cout << "Finshed" << std::endl;
}

void Form::on_pushButton_clicked()
{
 // Start the computation.
 QFuture<void> future = QtConcurrent::run(&this->MyObject, &MyClass::LongFunction);
 this->FutureWatcher.setFuture(future);

this->ProgressDialog->setMinimum(0);
 this->ProgressDialog->setMaximum(0);
 this->ProgressDialog->setWindowModality(Qt::WindowModal);
 this->ProgressDialog->exec();

}

form.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
 <property name="geometry">
 <rect>
 <x>0</x>
 <y>0</y>
 <width>400</width>
 <height>300</height>
 </rect>
 </property>
 <property name="windowTitle">
 <string>Form</string>
 </property>
 <layout class="QVBoxLayout" name="verticalLayout">
 <item>
 <widget class="QPushButton" name="pushButton">
 <property name="text">
 <string>PushButton</string>
 </property>
 </widget>
 </item>
 </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

MyClass.h

#ifndef MyClass_H
#define MyClass_H

#include <iostream>

class MyClass
{
public:

void LongFunction()
 {
 for( int count = 0; count < 5; count++ )
 {
 sleep( 1 );
 std::cout << "Ping long!" << std::endl;
 }
 }
};

#endif

FutureWatcherProgressDialog.cpp

#include <QApplication>

  1. include <QObject>
  2. include <QThread>
  1. include <iostream>
  1. include "form.h"

int main(int argc, char*argv[]) {

QApplication app(argc, argv);

Form form;

form.show();

return app.exec();