一、多线程与界面组件的通信
1、GUI设计原则
(1)、所有界面组件的操作都只能在主线程中完成
(2)、因此,主线程也叫UI线程
2、子线程对界面组件进行更新的解决方案-----信号与槽
(1)、在子线程类中定义界面更新信号(updateUI)
(2)、在窗口类中定义更新界面组件的槽函数(setInfo)
(3)、使用异步方式连接更新信号到槽函数(updateUI--->setInfo)
A、子线程通过发射信号的方式更新界面组件
B、所有界面组件对象只能依附主线程
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QString>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
signals:
void UpdataUI(QString text);
private:
void run();
public slots:
};
#endif // MYTHREAD_H
MyThread.h
MyThread.cpp
#include "MyThread.h"
#include<QString>
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}
void MyThread::run()
{
emit UpdataUI("begin");
for(int i=0; i<10; i++)
{
emit UpdataUI(QString::number(i));
sleep(1);
}
emit UpdataUI("end");
}
MyThread.cpp
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <QPlainTextEdit>
#include "MyThread.h"
class Widget : public QWidget
{
Q_OBJECT
private:
QPlainTextEdit* m_plaintext;
MyThread mythread;
protected slots:
void setInfo(QString text);
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif // WIDGET_H
Widget.h
mythread.cpp
#include "Widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_plaintext = new QPlainTextEdit(this);
m_plaintext->resize(160,160);
m_plaintext->setReadOnly(true);
connect(&mythread, SIGNAL(UpdataUI(QString)), this, SLOT(setInfo(QString)));
mythread.start();
}
void Widget::setInfo(QString text)
{
m_plaintext->appendPlainText(text);
}
Widget::~Widget()
{
}
mythread.cpp
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;//依附于主线程,而发射信号的不依附主线程,故根据默认方式,这里已经是异步模式
w.show();
return a.exec();
}
二、小结
(1)、现代GUI平台只允许在主线程中直接操作界面组件
(2)、Qt中可以借助信号与槽的机制在子线程中操作界面组件
(3)、进行信号与槽的连接时必须采用异步连接的方式
(4)、界面组件对象必须依附于主线程