QT线程
QT——线程
每一个线程自带事件循环
线程函数,不会在main的事件循环中执行
所以,我们碰到比较耗时的操作,我们就可以把这个操作放到线程中去完成,避免程序一卡一卡的
线程类:QThread
只要创建出一个QThread对象,就会立刻创建出一个线程
只不过该线程没有开始运行而已
QThread* thread = new QThread(this)
QThread线程如何运行
thread->start();
即使没写线程主函数,线程依旧能够正常运行
QThread start之后,会做一个判断:
if(有没有写线程主函数 == 1){
运行线程主函数
}else{
运行线程的事件循环
}
线程的2条使用路径
写一个线程主函数
QThread 类有虚函数run
只要重写了run函数,就相当于写了一个线程主函数
那么当 线程.start()之后,就会运行这个run函数
所以,我们要写一个 myThread,继承QThread,就可以重写myThread的run函数了
那么创建线程的时候,就不要再创建QThread了,而是创建myThread
QT、c的线程区别
1:一个QThread或者一个myThread,只会有一个线程
2:c语言线程,只要线程主函数结束运行,线程就结束运行了,剩下的就是资源回收的问题
QT线程,只要QThread对象一直存在,线程就一直存在,无论run函数是否结束
如果run函数结束运行了,想要重新运行的话,重新start就好了
3:c语言线程,只要有地址,什么数据都能访问
QT线程,不允许跨线程访问ui界面中的窗口的
线程如何结束运行
thread->terminate();
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include<QThread>
#include<QScreen>
#include<QApplication>
#include<QPixmap>
class myThread : public QThread
{
Q_OBJECT
public:
myThread(QObject*parent);
void run() override;
QScreen* screen;
signals:
void sndSignal(QPixmap pic);
};
#endif // MYTHREAD_H
#include "mythread.h"
myThread::myThread(QObject*parent):QThread(parent){
screen=QApplication::primaryScreen();
}
void myThread::run(){
while(1){
QPixmap pic=screen->grabWindow(0);
emit sndSignal(pic);
QThread::usleep(100);
}
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"mythread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void rcvSig(QPixmap pic);
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
myThread *thread;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
thread =new myThread(this);
QObject::connect(thread,&myThread::sndSignal,this,&Widget::rcvSig);
}
void Widget::rcvSig(QPixmap pic){
ui->textEdit->append("hahha");
pic=pic.scaled(ui->label->size());
ui->label->setPixmap(pic);
}
void Widget::on_pushButton_clicked()
{
thread->start();
}
void Widget::on_pushButton_2_clicked()
{
thread->terminate();
}
Widget::~Widget()
{
delete ui;
}
将一个事件,移动到线程的事件循环中去执行
QObject::moveToThread(目标线程地址 t)
谁调用这个函数,谁的所有事件,都会被移动到t的事件循环中去执行
但是,moveToThread()有限制:
1:调用moveToThread函数的组件,必须直接继承QObject,不能继承自QWidget 获取其他基类 2:调用moveToThread函数的组件,不能有父组件
所以,要自己写一个类,直接继承自QObject,还不能有父组件
class Worker : public QObject {
Q_OBJECT
public slots:
void doWork() {
// 耗时操作
emit workFinished();
}
signals:
void workFinished();
};
QThread* thread = new QThread;
Worker* worker = new Worker;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::workFinished, thread, &QThread::quit);
connect(worker, &Worker::workFinished, worker, &Worker::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
thread->start();