Progress Bar: Difference between revisions
No edit summary |
(Cleanup) |
||
(7 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:HowTo]] | {{LangSwitch}} | ||
[[Category:HowTo]] | |||
[[Category:Snippets]] | |||
[[Category:Tutorial]] | |||
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 [http://doc.qt.io/qt-5/qobject.html 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 [http://doc.qt.io/qt-5/qfuturewatcher.html QFutureWatcher] and [http://doc.qt.io/qt-5/qtconcurrentrun.html QtConcurrent::run()], this is extremely easy. Below we demonstrate how to use this technique with both a [http://doc.qt.io/qt-5/qprogressdialog.html QProgressDialog] and a [http://doc.qt.io/qt-5/qprogressbar.html QProgressBar]. | ||
== QProgressBar Example == | == QProgressBar Example == | ||
Line 13: | Line 11: | ||
=== 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(& | 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 139: | ||
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 190: | ||
=== 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: | |||
Form(QWidget '''parent = 0); | |||
private: | |||
< | QFutureWatcher<void> FutureWatcher; | ||
MyClass MyObject; | |||
QProgressDialog''' ProgressDialog; | |||
}; | |||
#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->ProgressDialog = new QProgressDialog(this); | ||
connect(& | 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 339: | ||
form.show(); | form.show(); | ||
return app.exec | return app.exec(); |
Latest revision as of 22:25, 27 June 2015
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>
- 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();