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_OBJECT

    public:
    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&#40;&#41;;
    

    }
    @

    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


  • Moderators

    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))



    1. 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).

    2. 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.


  • Moderators



  • 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 &parameter) {
    // ...
    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 ?


  • Lifetime Qt Champion

    Hi,

    A rule of thumb that generally applies:
    If you have an infinite loop subclass QThread

    For 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 ?


  • Lifetime Qt Champion

    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/


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.