Как использовать сигналы и слоты в Qt для межпоточной связи

Я хочу создать приложение, в котором пользователь нажмет QPushButton, и это вызовет дополнительный поток, который добавит некоторый текст в QListWidget в главном окне. Но по причине, которую я не могу понять, хотя сигнал из потока в главное окно испускается, он никогда не достигает пункта назначения. Возможно, потому что соединение не работает. Но почему это происходит вот мой код (мое приложение скомпилировано с использованием Visual Studio 2010):

мифочит.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

мифочит.cpp

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

мой диалог.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);
}

найти.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();
}

найти.про:

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

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

person Dragno    schedule 29.11.2012    source источник
comment
У вас опечатка в соединении: SLOT(receiveMsg(Qstring&)) должно быть SLOT(receiveMsg(QString&)). Вы должны запустить свое приложение в отладчике или в консоли, чтобы увидеть, что Qt пишет в stdout и stderr.   -  person Kamil Klimek    schedule 29.11.2012


Ответы (2)


Две вещи:

  1. Во втором вызове соединения Qstring необходимо заменить на 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. Используйте qRegisterMetaType, чтобы сделать QString& пригодным для использования.

все же советую прочитать

http://blog.qt.digia.com/blog/2010/06/17/вы-делаете-это-неправильно/

и комментарий Кари

http://blog.qt.digia.com/blog/2010/06/17/вы-делаете-это-неправильно/#comment-7925

однако при работе с потоками.

person Tim Meyer    schedule 29.11.2012
comment
Я попытался добавить вызов exec(), но ничего не произошло. Также пример Mandelbrot в документации Qt не использует exec(). - person Dragno; 29.11.2012
comment
Ваш второй вызов connect() возвращает false. Я пытаюсь выяснить, почему. - person Tim Meyer; 29.11.2012
comment
см. также stackoverflow.com/questions/4093159/ - person g19fanatic; 29.11.2012
comment
@Tim Meyer Не могли бы вы изменить http на https? Таким образом, указатели будут работать напрямую - person katang; 22.07.2019

Прежде всего, используйте квалификатор const для аргументов, если вы не планируете его изменять. После исправления опечатки в соединении SLOT(receiveMsg(Qstring&)) и изменения подписи сигналов и слотов на константные ссылки все работает нормально

person Kamil Klimek    schedule 29.11.2012