Dragno
Dragno

Reputation: 3124

How to use signals & slots in Qt for inter-threading communication

I want to make an application where the user will hit a QPushButton and this will trigger a secondary thread which will add some text to a QListWidget in the main window. But for a reason that I cannot figure out ,although the signal from the thread to the main window is emitted it never reaches the destination. Probably because the connection fails. But why this happens here is my code(my application is compiled using Visual Studio 2010):

mythread.h

#ifndef MY_THREAD_H
#define MY_THREAD_H
#include <QThread>
#include <QString>
class mythread:public QThread
{
    Q_OBJECT

public:
    void setName(QString& name);
signals:
    void sendMsg(QString& msg);
protected:
    void run();
private:
    QString m_name;
    QString msg;
};
#endif

mythread.cpp

#include "mythread.h"
void mythread::setName(QString& name)
{
    m_name=name;
}
void mythread::run()
{
    msg="Hello "+m_name;
    emit sendMsg(msg);
}

mydialog.h:

#ifndef MY_DIALOG_H
#define MY_DIALOG_H
#include <QtGui>
#include "mythread.h"
class mydialog:public QDialog
{
    Q_OBJECT
public:
    mydialog();
public slots:
    void receiveMsg(QString& msg);
    void fillList();
private:
    QListWidget list1;
    QPushButton btn1;
    QGridLayout layout;
    mythread thread;
};
#endif

mydialog.cpp:

#include "mydialog.h"
mydialog::mydialog()
{
    layout.addWidget(&list1,0,0);
    btn1.setText("Find");
    layout.addWidget(&btn1,0,1);
    setLayout(&layout);
    QString myname="leonardo";
    thread.setName(myname);
    connect(&btn1,SIGNAL(clicked()),this,SLOT(fillList()));
    connect(&thread,SIGNAL(sendMsg(QString&)),this,SLOT(receiveMsg(Qstring&)));
}
void mydialog::fillList()
{
    thread.start();
}
void mydialog::receiveMsg(QString& msg)
{
    list1.addItem(msg);
}

find.cpp:

#include <QApplication>
#include "mydialog.h"
int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    mydialog window;
    window.setWindowTitle("Find");
    window.show();
    return app.exec();
}

find.pro:

TEMPLATE = app
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .

# Input
HEADERS += mydialog.h mythread.h
SOURCES += find.cpp mydialog.cpp mythread.cpp

Upvotes: 1

Views: 845

Answers (2)

Tim Meyer
Tim Meyer

Reputation: 12600

Two things:

  1. In your second connect call, Qstring must be changed to QString
  2. Qt cannot deliver QString& accross threads by default. There's two ways to fix this:
    1. Change your Signals and Slots and the connect to use QString rather than QString&
    2. Use qRegisterMetaType in order to make QString& usable.

I still recommend reading

https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong

and Kari's comment

https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong#commento-comment-name-a6fad43dec11ebe375cde77a9ee3c4331eb0c5f0bcac478ecbe032673e8ebc82

when working with threads, though.

Upvotes: 2

Kamil Klimek
Kamil Klimek

Reputation: 13130

First of all use const qualifier for arguments if you're not planning to modify it. After fixing typo in connection SLOT(receiveMsg(Qstring&)) and changing signals and slots signature to const references everything works fine

Upvotes: 1

Related Questions