One solution would be to simply connect the finished() signal to a slot in MainWindow whose implementation calls update(). Note that delivery of this signal will be asynchronous because the sender and receiver objects are in different threads.
Here is a working example:
main.cpp
#include <QtGui/QApplication>
#include "stuff.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
stuff.h
#ifndef STUFF_H
#define STUFF_H
#include <QtGui/QMainWindow>
#include <QtCore/QThread>
class QLabel;
class Thread : public QThread
{
Q_OBJECT
public:
Thread(QObject *parent);
void run();
private:
void startWork();
signals:
void workFinished();
};
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow();
public slots:
void startWork();
void workFinished();
private:
QLabel* m_label;
Thread* m_thread;
};
#endif
stuff.cpp
#include <QtCore/QTimer>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QLabel>
#include "stuff.h"
#include <QDebug>
// Global variables used for ITC
QWaitCondition buttonPressed;
QMutex mutex;
Thread::Thread(QObject *parent)
: QThread(parent)
{
}
void Thread::run()
{
qDebug() << "Thread::run" << QThread::currentThreadId();
while (1) {
mutex.lock();
buttonPressed.wait(&mutex);
mutex.unlock();
startWork();
}
}
void Thread::startWork()
{
qDebug() << "Thread::startWork" << QThread::currentThreadId();
// Simulate some long-running task
sleep(3);
// Emit a signal, which will be received in the main thread
emit workFinished();
}
MainWindow::MainWindow()
: m_label(new QLabel(this))
, m_thread(new Thread(this))
{
QPushButton *button = new QPushButton("Start", this);
connect(button, SIGNAL(pressed()), this, SLOT(startWork()));
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(button);
layout->addWidget(m_label);
setLayout(layout);
// Create connection across thread boundary
connect(m_thread, SIGNAL(workFinished()), this, SLOT(workFinished()));
m_thread->start();
}
void MainWindow::startWork()
{
// Signal the thread to tell it that the button has been pressed
mutex.lock();
m_label->setText("Started");
buttonPressed.wakeAll();
mutex.unlock();
}
void MainWindow::workFinished()
{
qDebug() << "MainWindow::workFinished" << QThread::currentThreadId();
m_label->setText("Finished");
}