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

Qt学习记录(14)线程

前言:

我的臀部已经翘到可以顶起一屁股债了

为什么要使用线程

什么时候用线程

复杂的数据处理

头文件.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTimer>//定时器头文件QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void dealTimeout();//定时器槽函数private slots:void on_pushButton_clicked();private:Ui::Widget *ui;QTimer *myTimer;//声明变量
};
#endif // WIDGET_H

.cpp文件 

#include "widget.h"
#include "ui_widget.h"
#include <QThread>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myTimer=new QTimer(this);//只要定时器启动,自动触发timeout()connect(myTimer,&QTimer::timeout,this,&Widget::dealTimeout);
}void Widget::dealTimeout()
{static int i =0;i++;//设置LCD的值ui->lcdNumber->display(i);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//如果定时器没有工作if(myTimer->isActive()==false){myTimer->start(100);}//非常复杂的数据处理,耗时较长QThread::sleep(5);//处理完数据,关闭定时器myTimer->stop();qDebug()<<"over";
}

 现象

忘了录,而且不好展示,当按下start按键的时候,整个页面会卡住,不可移动和点击,LCD也没有变化,5秒后打印"over"

线程旧的用法

 

 添加QThread文件

添加新文件

 注意基类选择object

 .h和.cpp文件改基类和头文件

运行检查是否有错

QThread F1查询 Protected Function

protected://QThread的虚函数//线程处理函数//不能直接调用,通过start()间接调用void run();

 QThread的使用

mythread.h 线程头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = nullptr);
protected://QThread的虚函数//线程处理函数//不能直接调用,通过start()间接调用void run();
signals:void isDone();};#endif // MYTHREAD_H

mythread.cpp 线程主文件 

#include "mythread.h"MyThread::MyThread(QObject *parent) : QThread(parent)
{}void MyThread::run()
{//很复杂的数据处理//需要耗时5ssleep(5);emit isDone();
}

 widget.h主窗口头文件

添加了线程头文件,线程槽函数,线程停止函数,线程对象

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTimer>//定时器头文件
#include "mythread.h"//线程头文件QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void dealTimeout();//定时器槽函数void dealDone();//线程槽函数void stopThread();//停止线程槽函数
private slots:void on_pushButton_clicked();private:Ui::Widget *ui;QTimer *myTimer;//声明变量MyThread *thread;//线程对象
};
#endif // WIDGET_H

 widget.cpp 主窗口主文件

#include "widget.h"
#include "ui_widget.h"
#include <QThread>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myTimer=new QTimer(this);//只要定时器启动,自动触发timeout()connect(myTimer,&QTimer::timeout,this,&Widget::dealTimeout);//分配空间thread = new MyThread(this);connect(thread,&MyThread::isDone,this,&Widget::dealDone);//当按窗口右上角x时,窗口触发destroyed()信号connect(this,&Widget::destroyed,this,&Widget::stopThread);
}
void Widget::stopThread()
{//停止线程thread->quit();//等待线程处理完手中工作thread->wait();  
}void Widget::dealDone()
{qDebug()<<"it is over";myTimer->stop();
}
void Widget::dealTimeout()
{static int i =0;i++;//设置LCD的值ui->lcdNumber->display(i);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//如果定时器没有工作if(myTimer->isActive()==false){myTimer->start(100);}//启动线程,处理数据thread->start();
}

现象

5秒停止,打印"it is over"

线程新的用法

 

mythread.h头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>class MyThread : public QObject
{Q_OBJECT//如果没有这个宏就会报错
public:explicit MyThread(QObject *parent = nullptr);//线程处理函数void myTimeout();void setFlag(bool flag=true);signals:void mySignal();private:bool isStop;};#endif // MYTHREAD_H

 

mythread.cpp文件

#include "mythread.h"
#include <QThread>
#include <QDebug>
#include <QMessageBox>MyThread::MyThread(QObject *parent) : QObject(parent)
{isStop=false;
}void  MyThread::myTimeout()
{while(isStop==false){QThread::sleep(1);emit mySignal();//QMessageBox::aboutQt(NULL);qDebug()<<"子线程号:"<<QThread::currentThread();if(true==isStop){break;}}}void MyThread::setFlag(bool flag)
{isStop=flag;
}

 

widget.h头文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "mythread.h"
#include <QThread>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void dealSignal();void dealClose();
signals:void startThread();//启动子线程的信号private slots:void on_ButtonStart_clicked();void on_ButtonStop_clicked();private:Ui::Widget *ui;MyThread *myT;QThread *thread;};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//动态分配空间,不能指定父对象//指定父对象后,不能movemyT =new MyThread;//创建子线程thread =new QThread(this);//把自定义的线程加入到子线程中myT->moveToThread(thread);connect(myT,&MyThread::mySignal,this,&Widget::dealSignal);qDebug()<<"主线程号:"<<QThread::currentThread();connect(this,&Widget::startThread,myT,&MyThread::myTimeout);connect(this,&Widget::destroyed,this,&Widget::dealClose);//线程处理函数内部,不允许操作图形界面//connect()第五个参数的作用,连接方式:默认,队列,直接//多线程才有意义,//默认的时候//如果是多线程,默认使用队列//如果是单线程,默认使用直接方式//队列:槽函数所在线程和接收者一样//直接:槽函数所在线程和发送者一样
}Widget::~Widget()
{delete ui;
}void Widget::dealClose()
{on_ButtonStop_clicked();delete myT;
}void Widget::dealSignal()
{static int i=0;i++;ui->lcdNumber->display(i);}
void Widget::on_ButtonStart_clicked()
{if(thread->isRunning()==true){return;}//启动线程,但是没有启动线程处理函数thread->start();myT->setFlag(false);//不能直接调用线程处理函数//直接调用会导致线程处理函数和主线程是在同一个线程//myT->myTimeout();//只能通过 signal-slot方式调用emit startThread();
}void Widget::on_ButtonStop_clicked()
{if(thread->isRunning()==false){return;}myT->setFlag(true);thread->quit();//线程手头工作处理不完thread->wait();
}

现象

 在黑马的视频里面说,线程内部不能处理图形,但是我这里是运行出来的了,QMessageBox,但是后面又出问题,闪退了

线程画图

流程

mythread.h头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QImage>
#include <QObject>class MyThread : public QObject
{Q_OBJECT
public:explicit MyThread(QObject *parent = nullptr);//线程处理函数void drawImage();
signals:void updateImage(QImage temp);};#endif // MYTHREAD_H

mythread.cpp文件

#include "mythread.h"
#include<QPainter>
#include <QPen>
#include <QBrush>
#include <QThread>
MyThread::MyThread(QObject *parent) : QObject(parent)
{}
void MyThread::drawImage()
{//定义QImage绘图设备QImage image(500,500,QImage::Format_ARGB32);//定义画家,指定绘图设备QPainter p(&image);//定义画笔对象QPen pen;pen.setWidth(5);//设置宽度//把画笔交给画家p.setPen(pen);//定义画刷QBrush brush;brush.setStyle(Qt::SolidPattern);//设置样式brush.setColor(Qt::red);//设定颜色//把画刷交给画家p.setBrush(brush);//定义5个点QPoint a[] ={QPoint(qrand()%500,qrand()%500),QPoint(qrand()%500,qrand()%500),QPoint(qrand()%500,qrand()%500),QPoint(qrand()%500,qrand()%500),QPoint(qrand()%500,qrand()%500)};p.drawPolygon(a,5);//通过信号发送图片emit updateImage(image);}

widget.h头文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "mythread.h"
#include <QThread>
#include <QImage>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//重写绘图事件void paintEvent(QPaintEvent *);void getImage(QImage temp);void dealClose();//窗口关闭槽函数private:Ui::Widget *ui;QImage image;MyThread *myT;//自定义线程对象QThread *thread;
};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QThread>
#include <QPushButton>
#include <QImage>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//自定义类对象,分配空间,不可以指定父对象myT=new MyThread;//创建子线程thread=new QThread(this);//把自定义模块添加到子线程myT->moveToThread(thread);//启动子线程,但是并没有启动线程处理函数thread->start();//线程处理函数,必须通过signal -solt调用connect(ui->pushButton,&QPushButton::pressed,myT,&MyThread::drawImage);connect(myT,&MyThread::updateImage,this,&Widget::getImage);connect(this,&Widget::destroyed,this,&Widget::dealClose);}Widget::~Widget()
{delete ui;
}
void Widget::dealClose()
{//退出子线程thread->quit();//回收资源thread->wait();delete myT;}
void Widget::getImage(QImage temp)
{image=temp;update(); //更新窗口,间接调用painEvent()}void Widget::paintEvent(QPaintEvent *)
{QPainter p(this);//创建画家,指定绘图设备为窗口p.drawImage(50,50,image);
}

现象

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • pdf打开方式怎么设置默认?分享这几种设置方法
  • Ribbon负载均衡(自己总结的)
  • Wpf 使用 Prism 实战开发Day24
  • DA-CLIP论文阅读笔记
  • 如何在VSCode中修改默认终端
  • 如何使用JMeter 进行全链路压测
  • 【Linux取经路】线程同步——条件变量
  • 1、什么是模块化,为什么要模块化?2、衡量模块独立的定性标准是什么?用自己的话表达其含义3、如何理解信息隐藏和局部化?用自己的话或者例子表达其含义
  • JavaScript异步编程:理解和使用Promise、Async/Await
  • Sentinel的授权规则详解
  • 浅析FAT32文件系统
  • 洗地机十大品牌排名:2024十大值得入手的洗地机盘点
  • 高德地图PlaceSearch标记点清除
  • vite+ts+mock+vue-router+pinia实现vue的路由权限
  • C# NetworkStream 流的详解与示例
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • create-react-app做的留言板
  • echarts花样作死的坑
  • Java 网络编程(2):UDP 的使用
  • Javascript设计模式学习之Observer(观察者)模式
  • js中的正则表达式入门
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • mac修复ab及siege安装
  • October CMS - 快速入门 9 Images And Galleries
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • PHP面试之三:MySQL数据库
  • Redis 懒删除(lazy free)简史
  • vue-router的history模式发布配置
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 记一次和乔布斯合作最难忘的经历
  • 老板让我十分钟上手nx-admin
  • 聊聊hikari连接池的leakDetectionThreshold
  • 山寨一个 Promise
  • 深度学习中的信息论知识详解
  • 事件委托的小应用
  • 数据结构java版之冒泡排序及优化
  • 详解移动APP与web APP的区别
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 用Visual Studio开发以太坊智能合约
  • 阿里云服务器购买完整流程
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • ###C语言程序设计-----C语言学习(3)#
  • #git 撤消对文件的更改
  • (07)Hive——窗口函数详解
  • (4)STL算法之比较
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (层次遍历)104. 二叉树的最大深度