Взгляните на Сигналы и слоты между потоками . Если вы всегда используете сигналы и слоты для связи с рабочим потоком, Qt обрабатывает moveToThread для вас, если это необходимо, и вы использовали правильное соединение.
Редактировать: Я предполагаю, что автор статьи видел свою проблему, так как он вызывал start в конструкторе до того, как поток был фактически создан. Другими словами, не доверяйте стороннему коду вслепую.
Редактировать: В ответ на ваш комментарий посмотрите на пример Мандельброта под заголовком MandelbrotWidget Class Implementation
:
В случае соединений с очередями Qt должен хранить копию аргументов, которые были переданы сигналу, чтобы впоследствии он мог передать их в слот. Qt знает, как взять копию многих типов C ++ и Qt, но QImage не является одним из них. Поэтому мы должны вызвать функцию шаблона qRegisterMetaType (), прежде чем мы сможем использовать QImage в качестве параметра в подключениях в очереди.
Я считаю, что это немного устарело, вот допустимых мета-типов . Поскольку сигналы и слоты между потоками используют соединения в очереди, в большинстве случаев вам не нужно выполнять вызовы moveToThread.
Edit:
Я попытаюсь объяснить вещи с подобным примером:
mythread.h:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QMutex>
class MyThread : public QThread
{
Q_OBJECT
protected:
virtual void run();
signals:
void signalGUI(QString);
};
#endif // MYTHREAD_H
mythread.cpp:
#include "mythread.h"
#include <QString>
void MyThread::run()
{
qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
static int run = 0;
QString temp = QString("Run: %1").arg(run++);
qDebug("String address inside run %p", &temp);
emit signalGUI(temp);
}
mylineedit.h
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QLineEdit>
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit MyLineEdit(QWidget *parent = 0);
public slots:
void setText(const QString &string);
};
#endif // MYLINEEDIT_H
mylineedit.cpp
#include "mylineedit.h"
#include <QThread>
MyLineEdit::MyLineEdit(QWidget *parent) :
QLineEdit(parent)
{
}
void MyLineEdit::setText(const QString &string)
{
qDebug("Thread id inside setText %d",(int)QThread::currentThreadId());
qDebug("String address inside setText %p\n", &string);
QLineEdit::setText(string);
}
main.cpp:
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include "mythread.h"
#include "mylineedit.h"
//GUI calls a thread to do some job and sub update the text box once it is done
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QHBoxLayout * pH = new QHBoxLayout(&w);
QPushButton * pushButton = new QPushButton("Run Thread", &w);
MyLineEdit * lineEdit = new MyLineEdit(&w);
pH->addWidget(pushButton);
pH->addWidget(lineEdit);
w.show();
MyThread thread;
qDebug("Thread id %d",(int)QThread::currentThreadId());
QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(start())) ;
QObject::connect(&thread,SIGNAL(signalGUI(const QString&)),lineEdit,SLOT(setText(const QString&)));
return a.exec();
}
Пример вывода после нажатия кнопки:
Thread id 1088110320
Thread id inside run 1093176208
String address inside run 0x41288350
Thread id inside setText 1088110320
String address inside setText 0x974af58
Как видите, поток выполнения отличается от основного потока GUI. Кроме того, даже если вы передаете константную ссылку на QString, поскольку она пересекает границы потоков, она копирует ее.
Я настоятельно рекомендую прочитать Threads и QObject .