1、QT版本
QT5.1
2、下面的测试程序在QtCreator的Qt Gui应用(QDialog)模板修改而成
3、下面是测试代码
头文件
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QThread>
#include <QTimer>
class Object;
class Thread : public QThread
{
Q_OBJECT
public:
Thread(QObject *parent = 0);
Q_SIGNALS:
void signalA();
private slots:
void slotB();
void slotT(); //响应定时器的槽
private:
void run();
//定义为类成员与在run()函数中定义该对象指针对线程执行没影响
Object *object;
QTimer *t;
};
class Object : public QObject
{
Q_OBJECT
public:
Object(QObject *parent =0);
public slots:
void slotT();//响应定时器的槽
};
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
Q_SIGNALS:
void signalB();
private slots:
void slotA();
void slotBtnA();//响应按键ui->pushbutton
private:
Ui::Dialog *ui;
Thread *thread ;
};
#endif // DIALOG_H
源文件
#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
thread = new Thread(this);
connect(thread, SIGNAL(signalA()), this, SLOT(slotA()));
// connect(this, SIGNAL(signalB()), thread, SLOT(slotB()));
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(slotBtnA()));
qDebug()<<"Dialog Thread ID : "<<QThread::currentThreadId();
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::slotA()
{
qDebug()<<"Dialog::slotA Thread ID : "<<QThread::currentThreadId();
}
void Dialog::slotBtnA()
{
Q_EMIT(signalB());
}
Thread::Thread(QObject *parent):
QThread(parent)
{ //在构造函数定义(new)的对象都属于界面线程(主线程),下面测试的对象都在run()函数体里构建
start();
}
void Thread::run()
{
QTimer *t = new QTimer();
object = new Object();
/*
*object = new Object(this); 这样创建将会报警:
*QObject: Cannot create children for a parent that is in a different thread.
*(Parent is Thread(0x3dcea8), parent's thread is QThread(0x11fbe8d0), current thread is Thread(0x3dcea8)
*但程序可以运行,且下面定时器响应槽slotT()是在子线程执行的
*/
connect(t, SIGNAL(timeout()), this, SLOT(slotT()));//由于this这个对象属于主线程,故它的槽slotT是有主线程执行
connect(t, SIGNAL(timeout()), object, SLOT(slotT())); //同理object在子线程创建,故它的槽slotT是由子线程执行
t->start(3000);
Dialog *parentDlg = qobject_cast<Dialog*>(parent());
connect(parentDlg, SIGNAL(signalB()), this, SLOT(slotB()));//这个同上面一样,有主线程执行槽
qDebug()<<"Sub Thread ID : "<<QThread::currentThreadId();
Q_EMIT(signalA());
exec();
}
void Thread::slotB()
{
qDebug()<<"Thread::slotB Thread ID : "<<QThread::currentThreadId();
}
void Thread::slotT()
{
qDebug()<<"Thread::slotT Thread ID : "<<QThread::currentThreadId();
}
void Object::slotT()
{
qDebug()<<"Object::slotT Thread ID : "<<QThread::currentThreadId();
}
Object::Object(QObject *parent):
QObject(parent)
{
}
由此可总结出:
1)、子类化QThread的类的构造函数,创建它的线程执行,创建出的对象(thread),属于创建它的那个线程;
2)、两线程通过信号与槽通信,槽函数由哪个线程执行,主要看其对象属于哪个线程(即创建它的那个线程),和connect的调用位置无关
3)、在子线程中创建对象时,主要避免使用父线程创建的对象作为父对象