Progress Bar: Difference between revisions
Henri Vikki (talk | contribs) No edit summary |
(Cleanup) |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
{{LangSwitch}} | |||
[[Category:HowTo]] | [[Category:HowTo]] | ||
[[Category:Snippets]] | [[Category:Snippets]] | ||
[[Category:Tutorial]] | [[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. | 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. | ||
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();