Progress Bar: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Category:HowTo]] | [[Category:HowTo]] | ||
[[Category:Snippets]] | |||
[[Category:Tutorial]] | |||
[toc align_right= | [toc align_right="yes" depth="3"] | ||
= Progress Bar = | = 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 | 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":http://developer.qt.nokia.com/doc/qt-4.8/qobject.html 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 | However, using "QFutureWatcher":http://developer.qt.nokia.com/doc/qt-4.8/qfuturewatcher.html and "QtConcurrent::run()":http://developer.qt.nokia.com/doc/qt-4.8/qtconcurrentrun.html#run, this is extremely easy. Below we demonstrate how to use this technique with both a QProgressDialog and a QProgressBar. | ||
== QProgressBar Example == | == QProgressBar Example == | ||
Line 13: | Line 15: | ||
=== form.h === | === form.h === | ||
<code>#ifndef FORM_H | <code>#ifndef FORM_H | ||
#define FORM_H | |||
#include | #include "ui_form.h" | ||
#include | #include <QFutureWatcher> | ||
#include | #include "MyClass.h" | ||
class Form : public QWidget, private Ui::Form | class Form : public QWidget, private Ui::Form | ||
{ | |||
Q_OBJECT | |||
public slots: | public slots: | ||
void slot_finished(); | void slot_finished(); | ||
void on_pushButton_clicked(); | |||
public: | public: | ||
Form(QWidget *parent = 0); | |||
private:< | private: | ||
QFutureWatcher<void> FutureWatcher; | |||
MyClass MyObject; | |||
}; | |||
#endif | #endif | ||
</code> | |||
=== form.cpp === | === form.cpp === | ||
<code> | <code> | ||
#include <QtGui> | |||
#include <QImage> | |||
#include | #include "form.h" | ||
#include | #include <iostream> | ||
Form::Form(QWidget *parent) | Form::Form(QWidget *parent) | ||
: QWidget(parent) | |||
{ | |||
setupUi(this); | |||
this- | this->progressBar->setMinimum(0); | ||
this->progressBar->setMaximum(0); | |||
this->progressBar->hide(); | |||
connect(&this- | connect(&this->FutureWatcher, SIGNAL (finished()), this, SLOT (slot_finished())); | ||
} | } | ||
void Form::slot_finished() | void Form::slot_finished() | ||
{ | |||
this->progressBar->hide(); | |||
} | |||
void Form::on_pushButton_clicked() | void Form::on_pushButton_clicked() | ||
{ | |||
this->progressBar->show(); | |||
// Start the computation.< | // Start the computation. | ||
QFuture<void> future = QtConcurrent::run(&this->MyObject, &MyClass::LongFunction); | |||
this->FutureWatcher.setFuture(future); | |||
} | |||
</code> | |||
=== form.ui === | === form.ui === | ||
<code>< | <code> | ||
<?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> | |||
</code> | |||
=== FutureWatcher.cpp === | === FutureWatcher.cpp === | ||
<code>#include | <code>#include <QApplication> | ||
#include <QObject> | |||
#include <QThread> | |||
#include | #include <iostream> | ||
#include | #include "form.h" | ||
int main(int argc, char*argv[]) | int main(int argc, char*argv[]) | ||
{ | |||
QApplication app(argc, argv); | |||
Form form; | Form form; | ||
Line 73: | Line 143: | ||
form.show(); | form.show(); | ||
return app.exec | return app.exec(); | ||
}</code> | |||
=== MyClass.h === | === MyClass.h === | ||
<code> | <code> | ||
#ifndef MyClass_H | |||
#define MyClass_H | |||
#include | #include <iostream> | ||
class MyClass | class MyClass | ||
{ | |||
public: | |||
void LongFunction() | void LongFunction() | ||
{ | |||
for( int count = 0; count < 5; count++ ) | |||
{ | |||
sleep( 1 ); | |||
std::cout << "Ping long!" << std::endl; | |||
} | |||
} | |||
}; | |||
#endif | #endif | ||
</code> | |||
=== CMakeLists.txt === | === CMakeLists.txt === | ||
<code> | <code> | ||
cmake_minimum_required(VERSION 2.6) | |||
PROJECT (FutureWatcher) | PROJECT (FutureWatcher) | ||
FIND_PACKAGE(Qt4 REQUIRED) | FIND_PACKAGE(Qt4 REQUIRED) | ||
INCLUDE (${QT_USE_FILE}) | |||
QT4_WRAP_CPP(MOCSrcs form.h) | QT4_WRAP_CPP(MOCSrcs form.h) | ||
QT4_WRAP_UI(UISrcs form.ui) | |||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) | include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) | ||
ADD_EXECUTABLE(FutureWatcher FutureWatcher.cpp MyClass.cpp form.cpp ${MOCSrcs} ${UISrcs}) | ADD_EXECUTABLE(FutureWatcher FutureWatcher.cpp MyClass.cpp form.cpp ${MOCSrcs} ${UISrcs}) | ||
TARGET_LINK_LIBRARIES(FutureWatcher ${QT_LIBRARIES}) | |||
</code> | |||
== QProgressDialog Example == | == QProgressDialog Example == | ||
Line 105: | Line 194: | ||
=== form.h === | === form.h === | ||
<code> | <code> | ||
#ifndef FORM_H | |||
#define FORM_H | |||
#include | #include "ui_form.h" | ||
#include | #include <QFutureWatcher> | ||
#include | #include "MyClass.h" | ||
class QProgressDialog; | class QProgressDialog; | ||
class Form : public QWidget, private Ui::Form | class Form : public QWidget, private Ui::Form | ||
{ | |||
Q_OBJECT | |||
public slots: | public slots: | ||
void slot_finished(); | void slot_finished(); | ||
void on_pushButton_clicked(); | |||
public: | public: | ||
Form(QWidget '''parent = 0); | |||
#endif | private: | ||
QFutureWatcher<void> FutureWatcher; | |||
MyClass MyObject; | |||
QProgressDialog''' ProgressDialog; | |||
}; | |||
#endif | |||
</code> | |||
=== form.cpp === | === form.cpp === | ||
<code> | <code> | ||
#include <QtGui> | |||
#include <QImage> | |||
#include | #include "form.h" | ||
#include | #include <iostream> | ||
Form::Form(QWidget *parent) | Form::Form(QWidget *parent) | ||
: QWidget(parent) | |||
{ | |||
setupUi(this); | |||
this- | this->ProgressDialog = new QProgressDialog(this); | ||
connect(&this- | connect(&this->FutureWatcher, SIGNAL (finished()), this, SLOT (slot_finished())); | ||
connect(&this->FutureWatcher, SIGNAL (finished()), this->ProgressDialog , SLOT (cancel())); | |||
} | } | ||
void Form::slot_finished() | void Form::slot_finished() | ||
{ | |||
std::cout << "Finshed" << std::endl; | |||
} | |||
void Form::on_pushButton_clicked() | void Form::on_pushButton_clicked() | ||
{ | |||
// Start the computation. | |||
QFuture<void> future = QtConcurrent::run(&this->MyObject, &MyClass::LongFunction); | |||
this->FutureWatcher.setFuture(future); | |||
this- | this->ProgressDialog->setMinimum(0); | ||
this->ProgressDialog->setMaximum(0); | |||
this->ProgressDialog->setWindowModality(Qt::WindowModal); | |||
this->ProgressDialog->exec(); | |||
} | } | ||
</code> | |||
=== form.ui === | === form.ui === | ||
<code>< | <code> | ||
<?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> | |||
</code> | |||
MyClass.h | MyClass.h | ||
<code> | |||
#ifndef MyClass_H | |||
#define MyClass_H | |||
#include | #include <iostream> | ||
class MyClass | class MyClass | ||
{ | |||
public: | |||
void LongFunction() | void LongFunction() | ||
{ | |||
for( int count = 0; count < 5; count++ ) | |||
{ | |||
sleep( 1 ); | |||
std::cout << "Ping long!" << std::endl; | |||
} | |||
} | |||
}; | |||
#endif | #endif | ||
</code> | |||
=== FutureWatcherProgressDialog.cpp === | === FutureWatcherProgressDialog.cpp === | ||
<code>#include | <code>#include <QApplication> | ||
#include <QObject> | |||
#include <QThread> | |||
#include | #include <iostream> | ||
#include | #include "form.h" | ||
int main(int argc, char*argv[]) | int main(int argc, char*argv[]) | ||
{ | |||
QApplication app(argc, argv); | |||
Form form; | Form form; | ||
Line 178: | Line 343: | ||
form.show(); | form.show(); | ||
return app.exec | return app.exec(); |
Revision as of 08:46, 25 February 2015
[toc align_right="yes" depth="3"]
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":http://developer.qt.nokia.com/doc/qt-4.8/qobject.html 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":http://developer.qt.nokia.com/doc/qt-4.8/qfuturewatcher.html and "QtConcurrent::run()":http://developer.qt.nokia.com/doc/qt-4.8/qtconcurrentrun.html#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>
- 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();