Qt 学习第十四天:线程与多线程

1024程序员快乐,如果这博客让你学习到了知识,请给我一个免费的赞❤️

父子线程演示

一、创建界面文件

LCDnumber

二、创建mythread类,继承QObject

三、在MyThread.h文件做修改,并且加上函数声明

引入头文件,改变继承

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = 0);protected:void run(); // 入口函数 -- 需要start()启动signals:void sigDone();public slots:
};#endif // MYTHREAD_H

四、实现run方法

#include "mythread.h"MyThread::MyThread(QObject *parent) : QThread(parent)
{}void MyThread::run()
{// 模拟复杂的操作sleep(5); //休眠5semit sigDone();
}

五、使用计时器来控制LCDnumber

//计时器mytimer = new QTimer(this);myt = new MyThread(this);connect(mytimer, &QTimer::timeout, this, [=](){static int num = 0;ui->lcdNumber->display(num++);});

六、实现按钮的槽函数

void MyWidget::on_begin_clicked()
{//如果计时器开着if(mytimer->isActive() == true){return;}// 启动定时器mytimer->start(1000); // ms// 启动子线程myt->start();
}

子线程运行结束后,停止计数器

// 子线程信号,子线程运行结束停止计数器
    connect(myt, &MyThread::finished, mytimer, &QTimer::stop); 

完整代码

mythread.cpp

#include "mythread.h"MyThread::MyThread(QObject *parent) : QThread(parent)
{}void MyThread::run()
{// 模拟复杂的操作sleep(5); //休眠5semit sigDone();
}

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = 0);protected:void run(); // 入口函数 -- 需要start()启动signals:void sigDone();public slots:
};#endif // MYTHREAD_H

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>
#include <QDebug>MyWidget::MyWidget(QWidget *parent) :QWidget(parent),ui(new Ui::MyWidget)
{ui->setupUi(this);//计时器mytimer = new QTimer(this);myt = new MyThread(this);connect(mytimer, &QTimer::timeout, this, [=](){static int num = 0;ui->lcdNumber->display(num++);});// 子线程信号,子线程运行结束停止计数器connect(myt, &MyThread::finished, mytimer, &QTimer::stop);}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::on_begin_clicked()
{//如果计时器开着if(mytimer->isActive() == true){return;}// 启动定时器mytimer->start(1000); // ms// 启动子线程myt->start();
}

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>
#include <QTimer>
#include "mythread.h"namespace Ui {
class MyWidget;
}class MyWidget : public QWidget
{Q_OBJECTpublic:explicit MyWidget(QWidget *parent = 0);~MyWidget();private slots:void on_begin_clicked();private:Ui::MyWidget *ui;QTimer* mytimer;MyThread *myt;
};#endif // MYWIDGET_H

多线程演示

一、创建界面文件

LCDnumber

二、创建子线程Mywork类,继承QObject

三、在mywork.h文件加上函数声明,成员变量

#ifndef MYWORK_H
#define MYWORK_H#include <QObject>class MyWork : public QObject
{Q_OBJECT
public:explicit MyWork(QObject *parent = 0);// 业务处理函数void doMyWork();void setFlag(bool bl);signals:
public slots:private:bool isStop;
};#endif // MYWORK_H

四、父线程mywidget.h实现

引入头文件(包括子线程的头文件)、信号函数、槽函数

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QThread>
#include <QTimer>
#include <QWidget>
#include "mywork.h"namespace Ui {
class MyWidget;
}class MyWidget : public QWidget
{Q_OBJECTpublic:explicit MyWidget(QWidget *parent = 0);~MyWidget();signals:// 发信号, 让子线程工作void sigWorking();public slots:// 开始按钮void slotStart();// 关闭按钮void slotStop();// 定时器void slotTimeout();// 关闭线程void slotCloseThread();private:Ui::MyWidget *ui;QTimer *mytimer;MyWork *work;QThread *pthread; //子线程
};#endif // MYWIDGET_H

五、实现子线程mywork.cpp

比较简单、模拟线程处理作业

#include "mywork.h"
#include <QThread>
#include <QMessageBox>
#include <QDebug>MyWork::MyWork(QObject *parent) : QObject(parent)
{isStop = false;
}void MyWork::doMyWork()
{while(!isStop){// 操作QThread::sleep(1);  // 当前线程处理操作用了1s// 每执行一次循环发一次信号qDebug() << QThread::currentThread() << "sub thread";// QMessageBox::aboutQt(NULL);}
}void MyWork::setFlag(bool bl)
{isStop = bl;
}

六、实现mywidget.cpp

        多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口

不建议在析构函数中进行与线程相关的操作。析构函数通常用于以下几种情况:

  1. 使用 new 分配的内存需要使用 delete 释放动态分配的资源。
  2. 关闭文件或网络连接
  3. 断开信号和槽连接
  4. 日志记录与打印
/* 多线程使用注意事项:* 1. 业务对象, 构造的时候不能指定父对象* 2. 子线程中不能处理ui窗口(ui相关的类)* 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口*/mytimer  = new QTimer(this);// 1. 业务对象work = new MyWork();// 2. 子线程类pthread = new QThread(this);// 3. 移动业务对象到子线程work->moveToThread(pthread);// 5. 子线程工作connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);// 定时器connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);// 窗口析构的时候干掉线程connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);qDebug() << QThread::currentThread() << "main thread";void MyWidget::slotStart()
{if(mytimer->isActive() == true){return;}if(pthread->isRunning()){return;}mytimer->start(500);// 4. 启动子线程pthread->start();// 发信号, 让子线程工作emit sigWorking();
}void MyWidget::slotStop()
{if(mytimer->isActive() == false){return;}mytimer->stop();// 停止子线程pthread->quit();work->setFlag(true);
}void MyWidget::slotTimeout()
{static int num = 0;ui->lcdNumber->display(num++);
}
// 窗口析构的时候干掉线程
void MyWidget::slotCloseThread()
{work->setFlag(true);pthread->quit();pthread->wait();    // 等待线程手头上的工作处理完成
}

完整代码

mywork.cpp

#include "mywork.h"
#include <QThread>
#include <QMessageBox>
#include <QDebug>MyWork::MyWork(QObject *parent) : QObject(parent)
{isStop = false;
}void MyWork::doMyWork()
{while(!isStop){// 操作QThread::sleep(1);  // 当前线程处理操作用了1s// 每执行一次循环发一次信号qDebug() << QThread::currentThread() << "sub thread";// QMessageBox::aboutQt(NULL);}
}void MyWork::setFlag(bool bl)
{isStop = bl;
}

mywork.h

#ifndef MYWORK_H
#define MYWORK_H#include <QObject>class MyWork : public QObject
{Q_OBJECT
public:explicit MyWork(QObject *parent = 0);// 业务处理函数void doMyWork();void setFlag(bool bl);signals:
public slots:private:bool isStop;
};#endif // MYWORK_H

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QThread>
#include <QTimer>
#include <QWidget>
#include "mywork.h"namespace Ui {
class MyWidget;
}class MyWidget : public QWidget
{Q_OBJECTpublic:explicit MyWidget(QWidget *parent = 0);~MyWidget();signals:// 发信号, 让子线程工作void sigWorking();public slots:// 开始按钮void slotStart();// 关闭按钮void slotStop();// 定时器void slotTimeout();// 关闭线程void slotCloseThread();private:Ui::MyWidget *ui;QTimer *mytimer;MyWork *work;QThread *pthread; //子线程
};#endif // MYWIDGET_H

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>MyWidget::MyWidget(QWidget *parent) : QWidget(parent),ui(new Ui::MyWidget)
{ui->setupUi(this);/* 多线程使用注意事项:* 1. 业务对象, 构造的时候不能指定父对象* 2. 子线程中不能处理ui窗口(ui相关的类)* 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口*/mytimer  = new QTimer(this);// 1. 业务对象work = new MyWork();// 2. 子线程类pthread = new QThread(this);// 3. 移动业务对象到子线程work->moveToThread(pthread);// 5. 子线程工作connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);// 定时器connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);// 窗口析构的时候干掉线程connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);qDebug() << QThread::currentThread() << "main thread";/* connect 的第 5 参数* 1. 自动连接 -- 默认*      多线程 -- 指定队列连接*      单线程 -- 指定直接连接* 2. 队列连接 -- 多线程*      槽函数在信号接受者(receiver)所在的线程中执行* 3. 直接连接 -- 单线程*      信号和槽函数在同一个线程中执行*/
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::slotStart()
{if(mytimer->isActive() == true){return;}if(pthread->isRunning()){return;}mytimer->start(500);// 4. 启动子线程pthread->start();// 发信号, 让子线程工作emit sigWorking();
}void MyWidget::slotStop()
{if(mytimer->isActive() == false){return;}mytimer->stop();// 停止子线程pthread->quit();work->setFlag(true);
}void MyWidget::slotTimeout()
{static int num = 0;ui->lcdNumber->display(num++);
}
// 窗口析构的时候干掉线程
void MyWidget::slotCloseThread()
{work->setFlag(true);pthread->quit();pthread->wait();    // 等待线程手头上的工作处理完成
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实战:大数据冷热分析

实战&#xff1a;大数据冷热分析 冷热分析&#xff08;Hot and Cold Data Analysis&#xff09;的目的主要在于优化存储系统的性能和成本。通过识别并区分访问频率和存储需求不同的数据&#xff0c;可以采取适当的存储策略&#xff0c;进而提高系统的效率和用户体验。终极目的…

javaScript整数反转

function _reverse(number) { // 补全代码 return (number ).split().reverse().join(); } number &#xff1a;首先&#xff0c;将数字 number 转换为字符串。在 JavaScript 中&#xff0c;当你将一个数字与一个字符串相加时&#xff0c;JavaScript 会自动将数字转换为字符串…

PyTorch中如何进行向量微分、矩阵微分、计算雅各比行列式

文章目录 摘要Abstract 一、计算雅各比行列式二、向量微分三、矩阵微分总结 摘要 本文介绍了在PyTorch中进行向量微分、矩阵微分以及计算雅各比行列式的方法。通过对自动微分&#xff08;Autograd&#xff09;功能的讲解&#xff0c;展示了如何轻松实现复杂的数学运算&#xf…

代码编辑组件

代码编辑组件 文章说明核心代码运行演示源码下载 文章说明 拖了很久&#xff0c;总算是自己写了一个简单的代码编辑组件&#xff0c;虽然还有不少的bug&#xff0c;真的很难写&#xff0c;在写的过程中感觉自己的前端技术根本不够用&#xff0c;好像总是方案不够好&#xff1b;…

Flux 开源替代,他来了——Liberflux

LibreFLUX 是 FLUX.1-schnell 的 Apache 2.0 版本&#xff0c;它提供完整的 T5 上下文长度&#xff0c;使用注意力屏蔽&#xff0c;恢复了无分类器引导&#xff0c;并完全删除了 FLUX 美学微调/DPO 的大部分内容。 这意味着它比基本通量要难看得多&#xff0c;但它有可能更容易…

数据结构与算法汇总整理篇——数组与字符串双指针与滑动窗口的联系学习及框架思考

数组 数组精髓&#xff1a;循环不变量原则 数组是存放在连续内存空间上的相同类型数据的集合&#xff0c;通过索引(下标)访问元素&#xff0c;索引从0开始 随机访问快(O(1)时间复杂度)&#xff1b;插入删除慢(需要移动元素)&#xff1b;长度固定(部分语言中可动态调整) 其存…

解决电脑突然没有声音

问题描述&#xff1a;电脑突然没有声音了&#xff0c;最近没有怎么动过系统&#xff0c;没有安装或者卸载过什么软件&#xff0c;也没有安装或者卸载过驱动程序&#xff0c;怎么就没有声音了呢&#xff1f; 问题分析&#xff1a;仔细观察&#xff0c;虽然音量按钮那边看不到什…

索引的使用以及使用索引优化sql

索引就是一种快速查询和检索数据的数据结构&#xff0c;mysql中的索引结构有&#xff1a;B树和Hash。 索引的作用就相当于目录的作用&#xff0c;我么只需先去目录里面查找字的位置&#xff0c;然后回家诶翻到那一页就行了&#xff0c;这样查找非常快&#xff0c; 一、索引的使…

[Linux网络编程]06-I/O多路复用策略---select,poll分析解释,优缺点,实现IO多路复用服务器

一.I/O多路复用 I/O多路复用是一种用于提高系统性能的 I/O 处理机制。 它允许一个进程&#xff08;或线程&#xff09;同时监视多个文件描述符&#xff08;可以是套接字、管道、终端设备等&#xff09;&#xff0c;等待这些文件描述符中出现读、写或异常状态。一旦有满足条件的…

ts:类的创建(class)

ts&#xff1a;类的创建&#xff08;class&#xff09; 一、主要内容说明二、例子class类的创建1.源码1 &#xff08;class类的创建&#xff09;2.源码1的运行效果 三、结语四、定位日期 一、主要内容说明 class创建类里主要有三部分组成&#xff0c;变量的声明&#xff0c;构…

ts:数组的常用方法(filter)

ts&#xff1a;数组的常用方法&#xff08;filter&#xff09; 一、主要内容说明二、例子filter方法&#xff08;过滤&#xff09;1.源码1 &#xff08;push方法&#xff09;2.源码1运行效果 三、结语四、定位日期 一、主要内容说明 ts中数组的filter方法&#xff0c;是筛选数…

【STM32】单片机ADC原理详解及应用编程

本篇文章主要详细讲述单片机的ADC原理和编程应用&#xff0c;希望我的分享对你有所帮助&#xff01; 目录 一、STM32ADC概述 1、ADC&#xff08;Analog-to-Digital Converter&#xff0c;模数转换器&#xff09; 2、STM32工作原理 二、STM32ADC编程实战 &#xff08;一&am…

C++STL之stack

1.stack的使用 函数说明 接口说明 stack() 构造空的栈 empty() 检测 stack 是否为空 size() 返回 stack 中元素的个数 top() 返回栈顶元素的引用 push() 将元素 val 压入 stack 中 pop() 将 stack 中尾部的元素弹出 2.stack的模拟实现 #include<vector> namespace abc { …

LeetCode 热题 100之普通数组

1.最大子数组和 思路分析&#xff1a;这个问题可以通过动态规划来解决&#xff0c;我们可以使用Kadane’s Algorithm&#xff08;卡登算法&#xff09;来找到具有最大和的连续子数组。 Kadane’s Algorithm 的核心思想是利用一个变量存储当前的累加和 currentSum&#xff0c;并…

MATLAB生物细胞瞬态滞后随机建模定量分析

&#x1f3af;要点 基于随机动态行为受化学主方程控制&#xff0c;定量分析单细胞瞬态效应。确定性常微分方程描述双稳态和滞后现象。通过随机性偏微分方程描述出暂时性滞后会逐渐达到平稳状态&#xff0c;并利用熵方法或截断方法计算平衡收敛速度的估计值。随机定量分析模型使…

python查询并安装项目所依赖的所有包

引言 如果需要进行代码的移植&#xff0c;肯定少不了在另一台pc或者服务器上进行环境的搭建&#xff0c;那么首先是要知道在已有的工程的代码中用到了哪些包&#xff0c;此时&#xff0c;如果是用人工去一个一个的代码文件中去查看调用了哪些包&#xff0c;这个工作甚是繁琐。…

C++《vector的模拟实现》

在之前《vector》章节当中我们学习了STL当中的vector基本的使用方法&#xff0c;了解了vector当中各个函数该如何使用&#xff0c;在学习当中我们发现了vector许多函数的使用是和我们之前学习过的string类的&#xff0c;但同时也发现vector当中一些函数以及接口是和string不同的…

H5实现PDF文件预览,使用pdf.js-dist进行加载

H5实现PDF文件预览&#xff0c;使用pdf.js-dist进行加载 一、应用场景 在H5平台上预览PDF文件是在原本已经开发完成的系统中新提出的需求&#xff0c;原来的系统业务部门是在PC端进行PDF的预览与展示&#xff0c;但是现在设备进行了切换&#xff0c;改成了安卓一体机进行文件…

基于neo4j的课程资源生成性知识图谱

你是不是还在为毕业设计苦恼&#xff1f;又或者想在课堂中进行知识的高效管理&#xff1f;今天给大家分享一个你一定会感兴趣的技术项目——基于Neo4j的课程资源生成性知识图谱&#xff01;&#x1f4a1; 这套系统通过知识图谱的形式&#xff0c;将课程资源、知识点和学习路径…

前端页面样式没效果?没应用上?

当我们在开发项目时会有很多个页面、相同的标签&#xff0c;也有可能有相同的class值。样式设置的多了&#xff0c;分不清哪个是当前应用的。我们可以使用网页的开发者工具。 在我们开发的网页中按下f12或&#xff1a; 在打开的工具中我们可以使用元素选择器&#xff0c;单击我…