16、Qt线程(一):继承QThread,重写run

news2025/1/23 9:18:29

一、说明

Qt提供了3个类4种方式创建线程:

1、QThread

①继承QThread类,重写run()函数

②继承QObject类,使用moveToThread()函数

2、使用QtConCurrent并发模块的run()函数

3、继承QRunnable类

二、功能说明

1、通过继承QThread,重写run的方式实现多线程

2、点击“开始”按钮启动子线程,同时通过信号槽的方式给子线程发送“开始”字符串;

3、子线程每隔1秒向主线程发送累加数;

4、点击"停止"按钮,通过函数调用的方式停止子线程;

5、注:

①子线程构造函数、被主线程调用的函数(stop())和信号槽方式调用的函数(doSendData())都是在主线程

②只有run()和run()调用的函数showValue()在子线程

三、项目创建

1、新建Qt Widgets Application应用,名称为ThreadRun,基类选择QMainWindow;

2、mainwindow.ui中放入两个Push Button按钮,第一个text改为“开始”,objectNme改为startPushButton,第二个text改为“停止”,objectNme改为stopPushButton

3、添加新的C++类,名称为MyThread,基类设置为QThread

四、代码演示

1、mythread.h代码
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);

public slots:
    void stop(); //线程停止

    void doSendData(QString); //接收主线程发送的字符串

protected:
    void run(); //线程启动函数

signals:
    void sendValue(int); //给主线程发送累加数

private slots:
    void showValue(); //显示累加数

private:
    volatile bool stopped; //线程停止标识

    int value; //累加数
};

#endif // MYTHREAD_H

2、mythread.cpp代码

#include "mythread.h"
#include <QDebug>

MyThread::MyThread(QObject *parent) : QThread(parent)
{
    stopped = false;
    qDebug() << "创建 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::stop 线程停止
*/
void MyThread::stop()
{
    stopped = true;
    qDebug() << "stop 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::doSendData 接收显示主线程发送的字符串
* @param str
*/
void MyThread::doSendData(QString str)
{
    qDebug() << str << "doSendData 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::run 子线程开始,自动调用run()函数
*/
void MyThread::run()
{
    value = 0;

    qDebug() << "run 子线程id:" << QThread::currentThreadId();
    while(!stopped)
    {
        showValue();
        msleep(1000); //延迟1秒
    }
    stopped = false;
}

/**
* @brief MyThread::showValue 显示并给主线程发送累加数
*/
void MyThread::showValue()
{
    qDebug() << value << "show子线程id:"<< QThread::currentThreadId();

    emit sendValue(value); //数据发送给主线程
    value++;
}

3、mainwindow.h代码

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "mythread.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void sendData(QString); //给子线程发送字符串

private slots:
    void on_startPushButton_clicked();

    void on_stopPushButton_clicked();

    void doSendValue(int); //接收子线程发送的累加数

private:
    Ui::MainWindow *ui;

    MyThread *m_myThread; //子线程对象
};

#endif // MAINWINDOW_H

4、mainwindow.cpp代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "主线程id:" << QThread::currentThreadId();

    m_myThread = new MyThread(this);
    //接收子线程数据
    connect(m_myThread, &MyThread::sendValue, this, &MainWindow::doSendValue);
    //给子线程发送数据
    connect(this, &MainWindow::sendData, m_myThread, &MyThread::doSendData);

    ui->startPushButton->setEnabled(true);
    ui->stopPushButton->setEnabled(false);
}

MainWindow::~MainWindow()
{
    if(m_myThread->isRunning())
    {
        m_myThread->stop();
    }
    m_myThread->quit(); //将子线程停止
    m_myThread->wait(); //等待子线程的运行结束后再停止

    delete ui;
}

/**
* @brief MainWindow::on_startPushButton_clicked 线程开始
*/
void MainWindow::on_startPushButton_clicked()
{
    emit sendData("开始");

    qDebug() << "主线程 startButtonid:" << QThread::currentThreadId();

    m_myThread->start(); //子线程开始,自动调用run()函数

    ui->startPushButton->setEnabled(false);
    ui->stopPushButton->setEnabled(true);
}

/**
* @brief MainWindow::on_stopPushButton_clicked 线程停止
*/
void MainWindow::on_stopPushButton_clicked()
{
    qDebug() << "主线程 stopButtonid:" << QThread::currentThreadId();
    if(m_myThread->isRunning())
    {
        m_myThread->stop();
        ui->startPushButton->setEnabled(true);
        ui->stopPushButton->setEnabled(false);
    }
}

/**
* @brief MainWindow::doSendValue 接收子线程发送的累加数
* @param value
*/
void MainWindow::doSendValue(int value)
{
    qDebug() << value << "doSendValue 线程id:"<< QThread::currentThreadId();
}

五、运行测试

先点击开始,一会再点击停止,输出框输出如下内容,根据线程id来区分不同的线程

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

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

相关文章

FATFS文件系统

文件系统是为了存储和管理数据&#xff0c;而在存储设备上建立的一种组织结构。 Windows常用的文件系统&#xff1a; 1、FAT12 2、FAT16 3、FAT32 4、exFAT 5、NTFS FAT&#xff1a;File Alloction Table 文件分配表 在小型的嵌入式存储设备大多…

大模型托管平台Replicate,获2.9元B轮融资

大模型开源平台Replicate在官网宣布&#xff0c;获得4000万美元&#xff08;近2.9亿元&#xff09;B轮融资。本次由a16z领投&#xff0c;英伟达、Y Combinator等跟投。 Replicate的开源平台提供了超过25,000个模型&#xff0c;涵盖文本、图片、视频、音频、3D模型等领域。典型…

60.乐理基础-打拍子-V字打拍法

前置内容&#xff1a; 文字版 https://note.youdao.com/s/6FSSvGBf &#xff08;顺序参考&#xff1a;下方的视频版里面目录顺序&#xff09; 视频版 【四川音乐学院作曲硕士】教你零基础自学乐理保姆级教学-学习视频教程-腾讯课堂 文字版还有下图红框中三个专栏里的内容&a…

freemarkEngine文件ftl的可视化编辑

在做导出word文件功能时&#xff0c;需要准备ftl模板&#xff0c;设置一些通配符&#xff0c;之后通过相关编码&#xff0c;即可以实现业务数据渲染后导出word的功能。但是ftl文件一般我们看不太懂&#xff0c;所以可视化创建和修改就非常合适。 1、安装office2016版本&#x…

【Linux】权限篇(二)

权限目录 1. 前言2. 权限2.1 修改权限2.2 有无权限的对比2.3 另外一个修改权限的方法2.3.1 更改用户角色2.3.2 修改文件权限属性 3. 第一个属性列4. 目录权限5. 默认权限 1. 前言 在之前的一篇博客中分享了关于权限的一些知识&#xff0c;这次紧接上次的进行&#xff0c;有需要…

中国数字化进程简史(1980-2022)之二基础网络雏形

20世纪80年代数字化政策扶持信息化技术基础研究&#xff0c;一大批科研成果在90年代开始市场转化&#xff0c;随着中国大陆向外向型经济转型&#xff0c;1993年3月12日朱镕基副总理主持会议部署建设国家公用经济信息网为起点&#xff0c;拉开了一系列“金”字号工程规划建设的序…

LLM漫谈(一)| LLM可以取代数据分析师吗?

我想&#xff0c;在过去的一年里&#xff0c;我们每个人都不止一次想知道ChatGPT是否&#xff08;或者更确切地说&#xff0c;何时&#xff09;能够取代你的工作。 我们有一个共识&#xff0c;即Generative AI最近的突破将极大地影响我们每个人生活和工作。然而&#xff0c;我们…

使用OpenCV4实现工业缺陷检测的六种方法

目录 1 机器视觉2 缺陷检测3 工业上常见缺陷检测方法 1 机器视觉 机器视觉是使用各种工业相机&#xff0c;结合传感器跟电气信号实现替代传统人工&#xff0c;完成对象识别、计数、测量、缺陷检测、引导定位与抓取等任务。其中工业品的缺陷检测极大的依赖人工完成&#xff0c;…

DPDK单步跟踪(3)-如何利用visual studio 2019和visual gdb来单步调试dpdk

准备工作 因为时间的关系&#xff0c;我想到哪说到哪&#xff0c;可能没那么高的完成度。 但其实有心的人&#xff0c;看到这个标题&#xff0c;就关了本文自己能做了。 why和how to build debug version DPDK,见前两篇。这里我们准备开始。 首先&#xff0c;你有一台linux机…

【游戏篇】Scratch之饥饿的鱼

【作品展示】饥饿的鱼 操作&#xff1a;点击小绿旗&#xff0c;按下键盘方向或者利用鼠标移动&#xff0c;躲避大鱼的同时还要想办法吃到小鱼。

SecureCRT连接vmware虚拟机的centos系统配置

软件版本&#xff1a;VMware10.0.3&#xff0c;centos 7&#xff0c;securecrt 8.7.2 1&#xff0c;虚拟网络编辑器选择桥接模式&#xff0c; 2&#xff0c;如果不小心删除网络&#xff0c;centos关机状态下&#xff0c;选择恢复默认设置。 3&#xff0c;进入linux系统&#…

DRF之引入

目录 一、web应用模式 【1】前后端混合开发 【2】前后端分离 二、API接口 三、接口测试工具&#xff1a;Postman 四、RESTful API规范 【1】什么是RESTful 【2】RESTful API的规范 2.1 数据的安全保障 2.2 接口特征表现 2.3 多数据版本共存 2.4 数据即是资源&#…

助力硬件测试工程师之EMC项目测试。

1&#xff1a;更新该系列的目的 接下来的一个月内&#xff0c;将更新硬件测试工程师的其中测试项目--EMC项目&#xff0c;后续将会出安规等项目&#xff0c;助力测试工程师的学习。 2&#xff1a;如何高效率的展现项目的基础以及一些细节知识点 通过思维导图以及标准的规定进行…

【ubuntu 22.04】安装中文版系统、中文语言包和中文输入法

在系统安装中的键盘布局选择时&#xff0c;选择Chinese - Chinese&#xff0c;此时会自动安装所有的中文语言包和ibus中文输入法系统安装成功重启后&#xff0c;点击设置 - 区域和语言 - 管理已安装的语言 * 根据提示安装更新后&#xff0c;将汉语&#xff08;中国&#xff09;…

蚂蚁集团5大开源项目获开放原子 “2023快速成长开源项目”

12月16日&#xff0c;在开放原子开源基金会主办的“2023开放原子开发者大会”上&#xff0c;蚂蚁集团主导开源的图数据库TuGraph、时序数据库CeresDB、隐私计算框架隐语SecretFlow、前端框架OpenSumi、数据域大模型开源框架DB-GPT入选“2023快速成长开源项目”。 &#xff08;图…

simulink代码生成(一)——环境搭建

一、安装C2000的嵌入式环境&#xff1b; 点击matlab附加功能&#xff0c; 然后搜索C2000&#xff0c;安装嵌入式硬件支持包&#xff1b;点击安装即可&#xff1b;&#xff08;目前还不知道破解版的怎么操作&#xff0c;目前我用的是正版的这样&#xff0c;完全破解的可能操作…

LeetCode刷题--- 目标和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归递归、搜…

常用单片机认识

单片机有哪些类型: 51单片机 AVR 单片机 MSP430 STM8 STM32 DSP Linux FPGA

pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称及pip安装

问题原因 通常出现这种情况是因为cmd&#xff08;终端&#xff09;无法识别pip指令&#xff0c;环境变量中缺失pip程序路径&#xff0c;因此需要手动将pip所在路径添加到环境变量 确保环境中包含pip 通常情况下&#xff0c;配置的环境中都会默认包含pip&#xff0c;本文采用…

STM32的以太网外设+PHY(LAN8720)使用详解(6):以太网数据接收及发送

0 工具准备 1.野火 stm32f407霸天虎开发板 2.LAN8720数据手册 3.STM32F4xx中文参考手册1 以太网数据接收及发送 1.1 以太网数据接收&#xff08;轮询&#xff09; 1.1.1 检查是否接收到一帧完整报文 使用轮询的方式接收以太网数据是一种简单但是效率低下的方法&#xff0c;…