当前位置: 首页 > news >正文

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();

相关文章:

  • SQL_语法
  • 逐行拆解 C 语言:数据类型、变量
  • 【初探数据结构】线性表——链表(二)带头双向循环链表(详解与实现)
  • MySQL 架构、索引优化、DDL解析、死锁排查
  • 在ubuntu20.4中如何创建一个虚拟环境(亲测有效)
  • ubuntu20.04已安装 11.6版本 cuda,现需要通过源码编译方式安装使用 cuda 加速的 ffmpeg 步骤
  • 有效的括号(栈)
  • 【论文阅读笔记】ALSS-YOLO | 无人机(UAVs)、热红外(TIR)、野生动物探测、小目标、轻量级探测器
  • 【Node.js入门笔记1---初始Node.js)】
  • 笔记:代码随想录算法训练营day37:完全背包、518. 零钱兑换 II、377. 组合总和 Ⅳ、70. 爬楼梯 (进阶)
  • Python--网络编程(下)
  • GPTQ - 生成式预训练 Transformer 的精确训练后压缩
  • C++编程指南23 - 在无关线程之间共享资源时应使用shared_ptr
  • IntelliJ IDEA 华为云远程开发配置步骤
  • 通用文件模型
  • Axure设计之数据列表动态列设置/列筛选案例
  • 设计模式Python版 状态模式
  • 开发者社区测试报告(功能测试+性能测试)
  • 尚硅谷爬虫note14
  • ZooKeeper 基本概述
  • 学校 网站源码/怎么推广自己的微信号
  • 淘客推广网站怎么做/直接登录的网站
  • 建设征信注册中心网站/互联网营销师证书有用吗
  • 开封网站快速排名优化/北京正规seo搜索引擎优化价格
  • 怎么做网站弹幕/买链接网站
  • jsp网站开发论文/怎么注册网站 个人