Table of Content
Progress Bar
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 [developer.qt.nokia.com] 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 [developer.qt.nokia.com] and QtConcurrent::run() [developer.qt.nokia.com], 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"
- {
- Q_OBJECT
- public slots:
- void slot_finished();
- void on_pushButton_clicked();
- public:
- private:
- MyClass MyObject;
- };
- #endif
form.cpp
- #include <QtGui>
- #include <QImage>
- #include "form.h"
- #include <iostream>
- {
- 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.
- 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[])
- {
- 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;
- {
- Q_OBJECT
- public slots:
- void slot_finished();
- void on_pushButton_clicked();
- public:
- private:
- MyClass MyObject;
- };
- #endif
form.cpp
- #include <QtGui>
- #include <QImage>
- #include "form.h"
- #include <iostream>
- {
- setupUi(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.
- this->FutureWatcher.setFuture(future);
- this->ProgressDialog->setMinimum(0);
- this->ProgressDialog->setMaximum(0);
- 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>
- #include <QObject>
- #include <QThread>
- #include <iostream>
- #include "form.h"
- int main(int argc, char*argv[])
- {
- Form form;
- form.show();
- return app.exec();
- }

