先上代码:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QtCore/QObject>
class MyThread : public QThread
{
Q_OBJECT
signals:
void uiSignal(QString msg);
protected:
void run();
public:
explicit MyThread(QObject *parent = nullptr);
};
#endif // MYTHREAD_H
#include "MyThread.h"
MyThread::MyThread(QObject *parent) : QThread(parent)
{
}
void MyThread::run()
{
emit uiSignal(QString::fromLocal8Bit("Ready Go!!!"));
sleep(1);
for(int i=0; i<10; i++)
{
emit uiSignal(QString::number(i));
sleep(1);
}
emit uiSignal(QString::fromLocal8Bit("Ready End!!!"));
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QtWidgets/QWidget>
#include <QPlainTextEdit>
#include "MyThread.h"
#include <QPushButton>
#include <QDebug>
class Widget : public QWidget
{
Q_OBJECT
QPlainTextEdit m_text;
QPushButton m_btnStart;
MyThread m_thread;
QTextCodec* codec;
protected slots:
void uiSlot(QString msg);//处理线程发送信号的槽函数
void btnSlot();//处理按钮按下发送信号的槽函数
public:
Widget(QWidget *parent = nullptr);
~Widget();
};
#endif // WIDGET_H
#include "Widget.h"
#include <QString>
#include <QTextCodec>
#include <QVBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout* vLayout = new QVBoxLayout();
codec = QTextCodec::codecForName("GB18030");
m_text.appendPlainText(codec->toUnicode("多线程与界面组件的通信"));
m_text.setReadOnly(true);
m_btnStart.setText(codec->toUnicode("开始"));
vLayout->addWidget(&m_text);
vLayout->addWidget(&m_btnStart);
setLayout(vLayout);
connect(&m_thread, SIGNAL(uiSignal(QString)), this, SLOT(uiSlot(QString)));
connect(&m_btnStart, SIGNAL(clicked()), this, SLOT(btnSlot()));
}
void Widget::btnSlot()
{
m_thread.start();
}
void Widget::uiSlot(QString msg)
{
m_text.appendPlainText(msg);
}
Widget::~Widget()
{
m_thread.wait();
}
运行效果图:
子线程不能直接操作UI界面的,只有主线程(UI线程)才可以操作界面组件的, 本次实现方式是利用信号与槽函数中的异步连接,还有另一种方式是子线程自定义事件,然后给主线程发送事件,然后主线程在event函数中处理该事件。