QT多线程实战_Qt多线程开发项目

QT多线程实战_Qt多线程开发项目文章目录需求的提出多线程线程间通信需求的提出窗口本身就是一个死循环,在这样一个死循环中执行任何耗时的操作,都会导致程序崩溃。所以多线程对于窗口编程而言是必要的。例如,在窗口中拖入一个pushButton和lineEdit,将pushButton的名字改为pbStart,然后为其绑定一个函数,函数中创建一个死循环,并让死循环中的内容实时输出到lineEdit。接下来设计一个逻辑,当点击pbStart之后,开始执行死循环,同时按钮内容变为Stop;当按钮内容为Stop时,点击按钮,停止执行死循环。所以

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

本文源码:
QT多线程实战

需求的提出

窗口本身就是一个死循环,在这样一个死循环中执行任何耗时的操作,都会导致程序崩溃。所以多线程对于窗口编程而言是必要的。

例如,在窗口中拖入一个pushButtonlineEdit,将pushButton的名字改为pbStart,然后为其绑定一个函数,函数中创建一个死循环,并让死循环中的内容实时输出到lineEdit

接下来设计一个逻辑,当点击pbStart之后,开始执行死循环,同时按钮内容变为Stop;当按钮内容为Stop时,点击按钮,停止执行死循环。

所以,需要设计一个用于控制循环是否继续执行的成员变量,在MainWindow的头文件中添加私有成员bool flag。在cpp文件中添加flag = true

然后转到设计界面 ,右键pbStart按钮->转到槽->clicked()。从而MainWindow中添加了一个名为on_pbStart_clicked的函数,填充其内容为

void MainWindow::on_pbStart_clicked()
{ 
   
    int i= 0;
    bool flag = QString::compare(ui->pbStart->text(),"start");
    if(flag)
        ui->pbStart->setText("stop");
    while(flag){ 
   
        i++;
        ui->lineEdit->setText(QString::number(i));
    }
}

Jetbrains全家桶1年46,售后保障稳定

结果运行之后,果然陷入了死循环,程序也无法响应了,最过分的是lineEdit并没有变化,这个时候就要考虑多线程。

在这里插入图片描述

多线程

QThread是Qt中最基础的线程类,每个实例都可以控制一个线程。其传统的调用方式是,新建一个继承QThread的类,然后将耗时任务写入run函数。而自QT4.4之后,则建议通过moveToThread()函数来调用多线程。

首先新建一个类,在项目中Ctrl+N,在弹出对话框中选择Files and Classes->C/C++->C++ Class,定义类的名称为ThTest,并选中QObject

令该类继承QObject,将头文件中的ThTest改为

class ThTest : public QObject
{ 
   
    Q_OBJECT
public:
    ThTest();
    ~ThTest();
    void Func(void);
};

相应地,cpp文件的内容为

#include "thtest.h"
#include <QDebug>
#include <QThread>

ThTest::ThTest(){ 
   }
ThTest::~ThTest(){ 
   }

void ThTest::Func()
{ 
   
    int NowNum = 0;
    while(true){ 
   
        NowNum++;
        qDebug()<<NowNum<<QThread::currentThreadId();
    }
}

然后更改mainwindow的代码,在其头文件内容如下

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include <QObject>
#include <QDebug>
#include "thtest.h"

QT_BEGIN_NAMESPACE
namespace Ui { 
    class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{ 
   
    Q_OBJECT

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

signals:
    void ToThread(); // 信号
private slots:
    void on_pbStart_clicked();
private:
    Ui::MainWindow *ui;
    QThread *qThTest;
    ThTest *th1;
};
#endif

然后将cpp文件中的on_pbStart_clicked函数改为

void MainWindow::on_pbStart_clicked()
{ 
   
    qThTest = new QThread;
    th1 = new ThTest;
    connect(this,&MainWindow::ToThread,th1,&ThTest::Func);
    th1->moveToThread(qThTest);
    qThTest->start();
    emit ToThread();
}

其中,connectToThread函数和ThTest中的Func函数绑定在了一起。也就是说,当这边发射ToThread的信号的时候,Th1会执行Func这个函数。

所以,当线程启动后,通过emit发射ToThread信号,果然命令行中会持续输出数字了,同时窗口并不会死掉。

到了这一步,其实已经可以处理一些多线程任务了,但还不能把递增的NowNum显示到主窗口上,从而让lineEdit看上去有些鸡肋。为了实现在窗口上显示递增的数字,接下来需要做的就是线程间的通信。

线程间通信

得益于Qt的信号槽机制,多线程之间的通信并不复杂。乃至于,可以广义地认为emit ToThread()本身也是一个线程间通信的过程。

所以只需在on_pbStart_clicked中添加一条

connect(th1,SIGNAL(sendInt(int)),this,SLOT(getInt(int)));

意思就是th1发射一个sendInt(int)this接收一个getInt(int),这两个函数的名字无所谓,但一定不包含形参,而只有形参的数据类型。

接下来,在thtest.h中添加sendInt

signals:
    void sendInt(int);

并更改其Func函数

void ThTest::Func(){ 
   
    int NowNum = 0;
    while(true){ 
   
        QThread::sleep(1);
        emit sendInt(NowNum++);
    }
}

最后,在mainwindow.h中添加

private slots:
    void getInt(int);

以及cpp文件中的

void MainWindow::getInt(int num){ 
   
    ui->lineEdit->setText(QString::number(num));
}

这样,在点击start之后,就可以看到lineEdit上数字的变化了。

在这里插入图片描述

终止多线程

最后,回到一开始的需求,是点击start开始,然后按钮变为stop,点击stop后再停止。

考虑到terminate并不安全,故而采用终结while的方式来退出死循环。方法是在ThTest中添加一个bool类型的成员running,即在头文件中添加

public:
    bool running=true;

并更改源文件中的while循环

void ThTest::Func(){ 
   
    int NowNum = 0;
    while(running){ 
   
        emit sendInt(NowNum++);
        QThread::sleep(1);
    }
}

最后修改on_pbStart_clicked

void MainWindow::on_pbStart_clicked()
{ 
   

    bool flag = QString::compare(ui->pbStart->text(),"stop");
    qDebug()<<ui->pbStart->text();
    th1->running = flag;
    ui->pbStart->setText(flag?"stop":"start");
    if(flag){ 
   
        th1->moveToThread(qThTest);
        qThTest->start();
        emit ToThread();
    }
    else
        ui->lineEdit->setText("0");
}

并把th1等初始化过程移除去

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{ 
   
    ui->setupUi(this);
    qThTest = new QThread;
    th1 = new ThTest;
    connect(th1,SIGNAL(sendInt(int)),this,SLOT(getInt(int)));
    connect(this,&MainWindow::ToThread,th1,&ThTest::Func);
}

结果线程果然终止了

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234553.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Jenkins安装_ansible jenkins

    Jenkins安装_ansible jenkins前言jenkins的环境搭建方法有很多,本篇使用docker快速搭建一个jenkins环境。环境准备:mac/Linuxdockerdocker拉去jenkins镜像先下载jenkins镜

    2022年7月28日
    4
  • minio节点扩展_多节点部署定时任务

    minio节点扩展_多节点部署定时任务1.概述分布式Minio可以让你将多块硬盘(甚至在不同的机器上)组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助你搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。数据保护分布式Minio采用纠删码来防范多个节点宕机和位衰减bitrot。分布式Minio至少需要4个硬盘,使用分布式Minio自动引入了纠删码功能。高可用单机Mi..

    2022年10月8日
    0
  • JavaScript之正则表达式的使用方法详细介绍[通俗易懂]

    JavaScript之正则表达式的使用方法详细介绍[通俗易懂]首先必须说明的是,这类文章(js正则表达式)在c站或者整个it类论坛是很多人写过的,而我认为我这篇的不同之处在于更加“小白”化,这也与我一贯的风格有关吧。关于JavaScript正则表达式,其他的文章大多一上来就太过激进,不利于初学者学习(我当粗就是这么被劝退的),这也是我为什么要坚持写这篇文章,希望小白在看了这篇文章后,不管能不能完全掌握JavaScript正则表达式,但至少对JavaScript正则表达式能有一个比较深刻的印象吧。

    2022年10月24日
    1
  • UITabBarController详细说明(简介和设置)

    UITabBarController详细说明(简介和设置)

    2022年1月14日
    44
  • 2021pycharm 激活码[在线序列号]

    2021pycharm 激活码[在线序列号],https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月20日
    63
  • python后端框架有哪些_后端框架有哪些?五款优秀的web开源后端框架推荐

    python后端框架有哪些_后端框架有哪些?五款优秀的web开源后端框架推荐作为一个web开发人员,下面五款优秀的开源框架一定要了解一下。PHP篇作为全球最好的web开发编程语言,PHP的框架非常多。下面重点介绍2款:Laravelhttps://laravel.comLaravel最大的优势就是:简洁和优雅。能迅速的让大家从杂乱无章的代码中解脱出来。拥抱PHP7基于composer全栈型框架灵活的路由配置仅仅通过配置文件就可以切换缓存、会话的存储介质,包括(file、r…

    2022年6月8日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号