Sunday, June 1, 2008

Qt: simple example of use of QtConcurrent

In this example we assume that a function my_func takes a long time to run, and would cause the GUI to freeze if it were run in the main GUI thread. In order to avoid the GUI freezing, we run my_func in a separate thread. The GUI will be therefore be fully functional while my_func is running.

When this application launched, a small GUI will appear containing a single button. When the button is clicked, the function my_func is run in a separate thread. When the thread finishes running, a message appears on the screen.

This example makes uses QtConcurrent::run(), QFuture and QFutureWatcher, rather than just a QThread. Qt 4.4.0 or above is required.

This example consists of the following codes: main.C, user_def.h, window.C and window.h.


Here we define the time-consuming operation. In this example, it is just a summation.
#include <QApplication>

#include "window.h"
#include "user_def.h"

// the user's time-consuming function

void my_func(void)
// time-consuming code
double sum;
for (int i=0; i<100000; i++)
for (int j=0; j<100000; j++)
sum = sum * i / j;

// main program

int main (int argc, char **argv)
QApplication app(argc, argv);
Window window;;
return app.exec();

#ifndef USER_DEF_H_
#define USER_DEF_H_

void my_func(void);

#endif /*USER_DEF_H_*/


Here we setup a very simple GUI just containing a single button. When the button is clicked, the time-consuming operation my_func is run in another thread when QtConcurrent::run() is called. We use a QFutureWatcher to monitor the state of the other thread. When the GUI thread receives a signal from the QFutureWatcher that the function has finished running, it displays a message on the screen using a QMessageBox.

#include "window.h"

// the main GUI

// constructor

Window::Window(QWidget *parent) : QWidget(parent)
setWindowTitle("Qt example 03");
runButton = new QPushButton("Run the function...");
connect(runButton, SIGNAL(clicked()),
this, SLOT(run_thread()));

QHBoxLayout *layout = new QHBoxLayout;

// create a QFuture and a QFutureWatcher

future = new QFuture<void>;
watcher = new QFutureWatcher<void>;

// display a message box when the calculation has finished

connect(watcher, SIGNAL(finished()),
this, SLOT(displayFinishedBox()));


// slot

void Window::run_thread()
*future = QtConcurrent::run(my_func);

// display message

void Window::displayFinishedBox()
QMessageBox::information(this, tr("Qt Example 03"),
tr("The function my_func has finished."));

#ifndef WINDOW_H_
#define WINDOW_H_

#include <QPushButton>
#include <QThread>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>

#include "user_def.h"

class Window : public QWidget

Window(QWidget *parent = 0);

QPushButton *runButton;
QFuture<void> *future;
QFutureWatcher<void> *watcher;

public slots:
void run_thread();
void displayFinishedBox();

#endif /*WINDOW_H_*/

This example can be compiled easily using:

qmake -project


Debayan said...

Very helpful. Thanks.

Olivier said...

many thanx really usefull example , i got it bookmarked =)

hasanyavuz said...

me too :)

Eduardo J. said...

Thanks. That´s very useful to satrt.

Isma said...

Thank you!
Exactly what I was looking for =)