0

I want to update UI from the second thread, I have created slots which are going to be called from other thread by signaling, but somehow it is not being called from the other thread. Below is the code:

WorkerThread.h

class WorkerThread: public QObject
{
    Q_OBJECT
public:
    WorkerThread();
    ~WorkerThread();

public slots:
    void onStart();
signals:
    void sendMessage(const QString& msg, const int& code);
};

WorkerThread.cpp

#include "workerwhread.h"

WorkerThread::WorkerThread(){}

void WorkerThread::onStart(){
    emit sendMessage("start", 100);
}

Usage:

MyWidget.h

namespace Ui {
class MyWidget;
}

class MyWidget: public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
private slots:
    void onGetMessage(const QString &msg, const int& code);
private:
    Ui::MyWidget *ui;
    QThread *thread = nullptr;
    WorkerThread *wt = nullptr;
};

MyWidget.cpp

MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    wt = new WorkerThread;
    thread = new QThread;

    connect(thread, &QThread::finished, wt, &QObject::deleteLater);
    connect(ui->btStart, &QPushButton::clicked, wt, &WorkerThread::onStart);
    connect(wt, &WorkerThread::sendMessage, this, &MyWidget::onGetMessage);
    wt->moveToThread(thread);
    thread->start();
}
void MyWidget::onGetMessage(const QString &msg, const int& code)
{
    qDebug() << "message" << msg; // this never being called ????
}

Note: When I pass the connection type Qt::DirectConnectoin, then it is working, but the problem is it is not the GUI thread.

connect(wt, &WorkerThread::sendMessage, this, &MyWidget::onGetMessage, Qt::DirectConnection);

Main

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    w.setWindowIcon(QIcon(":/icons/system.png"));
    return a.exec();
}
Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68
  • Did you run qmake? If `Qt::DirectConnection` works it most likely indicates Q_OBJECT is missing or no QEventLoop is running. As you told Qt::DirectConnection is working - thus, your slot/signal connections are fine. You placed Q_OBJECT and have an eventloop. So there is no obvious error. – user3606329 Mar 25 '18 at 17:56
  • I cannot reproduce your problem: with the same code, `message "start"` is printed when pressing the button, so the `onGetMessage` slot is called. There doesn't seem to be an error in the posted code. – Akos Bannerth Mar 25 '18 at 17:59
  • I know the code is really nice and clean, and I am master in writing clean and optimized code, but whatever I have done, it still not working. I am now going to be confusing with Qt single-slot mechanism. Wasted me a lot of time. – Bahramdun Adil Mar 25 '18 at 18:18
  • Should there be some connection between QThread signal started and a corresponding slot in WorkerThread? Maybe the thread just finishes right away with no work. See https://stackoverflow.com/a/11039216/5781248 – J.J. Hakala Mar 25 '18 at 19:58
  • I tested your code on my machine and it's working, I'm using Qt 5.9.4 and I'm running on Fedora 27, also instead of `MyWidget`, I'm using `MainWindow`, what is your working environment? – Simon Mar 26 '18 at 07:37
  • My environment is Qt 5.10.0, and the Qt designer is 4.5.0. Win 10. If it is working on your machine, then it means there is something wrong with 10.0 version? – Bahramdun Adil Mar 26 '18 at 07:41

1 Answers1

0

After a lot of trying and checking the code line by line, I finally found the problem. The reason was with overriding the event() function of QWidget, the return value of event() function is bool, so if you return a true it is OK and working well without throwing any runtime or compile-time error. But it will prevent signal-slot events to happen.

So NOT return true, but return QWidget::event(event); then it will slove the problem.

Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68