Access a label from inside another thread
-
Currently i have code that start and stops a thread that counts to 10000. What i now what to do is pass the current number inside the QObject thread to the ui thread so that i can set the text for the label. I thought it might be using connect but i just can't seemed to get it right.
maybe something like this ?
@connect(this,SIGNAL(worker()),&ui,SLOT(ui->label->settext((QString::number(thread->timealive))));@If anyone can help or point me in the right direction or even better have a basic example so i can get my head round it. Code listed below:
Dialog.h
@#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECTpublic:
explicit Dialog(QWidget *parent = 0);
~Dialog();private slots:
void on_pushButton_clicked();void on_pushButton_2_clicked(); void on_pushButton_3_clicked(); void on_pushButton_4_clicked(); void on_pushButton_5_clicked(); void on_pushButton_6_clicked();
private:
Ui::Dialog *ui;
};#endif // DIALOG_H
@object.h
@#ifndef OBJECT_H
#define OBJECT_H#include <QObject>
#include <QDebug>
#include <QThread>
#include <QApplication>
#include <QMutex>class Object : public QObject
{
Q_OBJECT
private:
int timealive;
public:
explicit Object(QObject *parent = 0);
void setup(QThread &thread, QObject &object);
void set_time(int number);
int get_time();
bool Stop;
signals:public slots:
int worker();
};#endif // OBJECT_H
@dialog.cpp
@#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}Dialog::~Dialog()
{
delete ui;
}void Dialog::on_pushButton_clicked()
{
connect(&thread,SIGNAL(),this,SLOT()
ui->label->setText(QString::number());
}void Dialog::on_pushButton_2_clicked()
{
//this->Sto
}void Dialog::on_pushButton_3_clicked()
{}
void Dialog::on_pushButton_4_clicked()
{}
void Dialog::on_pushButton_5_clicked()
{}
void Dialog::on_pushButton_6_clicked()
{}
@main.cpp
@#include "dialog.h"
#include "object.h"int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();QThread thread; Object thread_object; thread_object.Stop = false; thread_object.setup(thread,thread_object); return a.exec();
}
@object.cpp
@#include "object.h"
#include "dialog.h"Object::Object(QObject *parent) :
QObject(parent)
{
}void Object::setup(QThread &thread,QObject &object)
{object.moveToThread(&thread); thread.start(); connect(&thread,SIGNAL(started()),this,SLOT(worker()));
connect(this,SIGNAL(worker()),&ui,SLOT(ui->label->settext((QString::number(thread->timealive))));
}int Object::worker()
{
int i;
for(i = 0; i < 10000; i++)
{
QMutex mutex;
QMutexLocker locker(&mutex);
this->set_time(i);
qDebug() << i;
if(this->Stop)
{
break;
}
}
Dialog::
return i;
}void Object::set_time(int number)
{
timealive = number;
}int Object::get_time()
{
return timealive;
}
@on the main form all there is, is a start, stop and a label repeated 3 times. If anyone has any ideas please let me know i'm very new to Qt so this has been quite confusing for me.
Cheers Ion
-
You are doing it wrong :)
Connect statement should reside in the main (GUI) thread
In this case it should be a Qt::QueuedConnection to avoid problems (no need for any mutexes this way)
You have to define a slot and connect to it: you are not allowed to put any logic inside the connect statement unless you are using the new lambda syntax
connect thread signals before you start the thread! Otherwise you might miss signals sent in the beginning of execution!
I would personally connect the QThread outside of threaded object, but that I guess is your choice
please see QThread documentation for more info (just make sure the docs are sufficiently new (Qt 5.1 or Qt 4.8.5))
-
-
Cheers Sierdzio quick question do you know of any links that detail how to create a thread outside of a class ? As that seems to make alot more sense to me than doing it the way I am currently (if that's what you meant anyway).
-
Sadly for me the QThread documentation is completely rubbish as it only contains the old method of using QThread (using a subclass) so hasn't helped much so far will keep looking though.
-
-
Incorrect :) See here: "link":http://qt-project.org/doc/qt-5.0/qtcore/qthread.html.
Also consider "this":http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ and "this":http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html.
-
Sadly sierdzio those links have just made me more confused. Should i be using QThread as a subclass or not ?(what is the best method?), as everyone keeps telling me i shouldn't have QThread as a subclass, so now even more confused than before :D.
So is this the code i should be using ?
@class Worker : public QObject
{
Q_OBJECT
QThread workerThread;public slots:
void doWork(const QString ¶meter) {
// ...
emit resultReady(result);
}signals:
void resultReady(const QString &result);
};class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};@or should i have movetothread outside of the class aswell ?
-
Hi,
A rule of thumb that generally applies:
If you have an infinite loop subclass QThreadFor a nice working example (in this case for images but the same applies for numbers) look at the "Mandelbrot example":http://qt-project.org/doc/qt-4.8/threads-mandelbrot.html
-
Cheers SGaist thats what i needed to know as need to have the Gui working while a IP stream is coming in.
Also is Qtconcurrent worth implementing if u know that you will be dealing with a maximum of two threads (Gui+ one more)?
Also anything wrong with creating the thread outside of the object class and just moving that object into a thread ?
-
Are you thinking about network connection ? Qt provides QNetworkAccessManager which is already asynchronous, so you could use it directly with your GUI.
It all depends on your use case
Nothing wrong with it at all
-
Just R&D atm it's why I am looking at Qt. Cheers for the heads up ill have a look and see at that network access manager.
Yea been seeing Qthread all wrong so seems kind of simple now :P. Nightmare when your the only one who knows a language.
@{
MyClasswitheventloopsandslots *object
QThread *aThread = new QThread(this)
object->moveToThread(aThread);
connect(aThread, SIGNAL(started()),object,SLOT(startEventLoop());
aThread->start();
}@
"Where it finally clicked":http://www.youtube.com/watch?v=MMFhc2jXzgw
Help alot along with the links already posted, but to really get a good up to date version of what should be used.
Now QThread is staying outside of my Object class for good along with move to thread makes the code look so much more of a mess otherwise.
-
Hi,
Subclassing QThread is in my opinion a very tricky thing. Even in the mandelbrot example as SGalst pointed to the big problem lies in the use of memory. When you subclass QThread the constructor is owned by the main thread, not by the thread he is himself. Only when you movetothread(x) the subclass thread will be running, but all the memory allocated in the constructor is still "owned" by the main thread. This is just a accident to happen when 1 thread fools around with the data in the heap of another thread.
Here is a good post:
"Thread done better":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/