QThread的应用——在线程里面更新QProgressBar进度条

news2024/11/16 13:13:19

在线程里面更新QProgressBar进度条

编写QT软件的时候,经常会遇到点击某个按钮,进行一个比较耗时的计算。为了在计算过程中,软件界面就继续响应用户的点击,不会有卡死的感觉,一般会将这个耗时的计算放在另外一个线程里面,同时在界面上布置一个进度条(QProgressBar),显示当前的计算进度,提高软件的界面以及响应性。

下面就这一看似简单实则暗藏玄机的编程过程进行抽丝剥茧的解释。

代码实现

软件的界面比较简单,如下图所示:
在这里插入图片描述

使用QT时,在线程里面执行计算的时候,修改界面元素,有多种方法,最常见的就是两种:1)继承QThread,然后重写run,把耗时的计算代码放在run函数里面,同时定义进度更新的信号;2)定义一个继承自QObject的Worker类,里面定义进度更新信号,然后使用moveToThread的方法,将该类绑定到另外一个线程,在主线程里面,将按钮的信号和Worker的槽函数连接后,按钮信号的触发,就会触发Worker的槽函数在其绑定的线程里面执行。

使用moveToThread方法

下面是使用moveToThread的方法来定义一个Worker类:

class Worker : public QObject
{
    Q_OBJECT
  public:
    ~Worker() { std::cout << "worker is destructed!\n"; }

  public slots:
    void stop() { m_stopped = true; }

    int long_time_compution()
    {
        m_stopped = false;
        std::cout << "start long time compution ...\n";
        int i = 0;
        while (!m_stopped && i++ < 100)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            emit progressValueUpdated(i);
            std::cout << std::format("i: {}\n", i);
        }
        std::cout << std::format("finish long time compution, result: {}\n", i);
        emit resultReady(QString("Result: %1").arg(i));
        return i;
    }

  signals:
    void progressValueUpdated(int);
    void resultReady(QString);

  private:
    std::atomic_bool m_stopped{false};
};

我们定义了两个槽函数start和stop,以及两个信号progressValueUpdated和resultReady。

再看一下界面窗口的定义以及如何连接信号和槽函数:

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QMainWindow win;
    auto widget = new QWidget;
    auto layout = new QVBoxLayout;
    widget->setLayout(layout);
    win.setCentralWidget(widget);
    QProgressBar *bar = new QProgressBar;
    layout->addWidget(bar);
    auto btn_start = new QPushButton("Start");
    layout->addWidget(btn_start);
    auto btn_stop = new QPushButton("Stop");
    layout->addWidget(btn_stop);
    auto result_label = new QLabel("Result:");
    layout->addWidget(result_label);
    
    // 下面的worker要绑定的线程
    QThread worker_thread; 
    Worker worker;
    // 将worker绑定到单独的线程
    worker.moveToThread(&worker_thread);
    
    // 开始按钮的点击信号和worker的start槽函数连接起来
    QObject::connect(btn_start, &QPushButton::clicked, &worker, &Worker::long_time_compution);
    // 停止按钮的点击信号和worker的stop槽函数连接起来
    QObject::connect(btn_stop, &QPushButton::clicked, &worker, &Worker::stop, Qt::DirectConnection);
    // worker的进度更新信号和界面上的进度条连接起来
    QObject::connect(&worker, &Worker::progressValueUpdated, bar, &QProgressBar::setValue);
    QObject::connect(&worker, &Worker::resultReady, result_label, &QLabel::setText);
    
    // 开启工作线程的事件循环
    worker_thread.start();

    win.show();
    app.exec();
    
    // 退出工作线程的事件循环
    worker_thread.quit();
    // 等待线程当前执行的任务完成并退出
    worker_thread.wait();
}

上面的代码第一部分是界面设置,第二部分的连接界面和Worker的信号与槽,需要注意的是QObject::connect(btn_stop, &QPushButton::clicked, &worker, &Worker::stop, Qt::DirectConnection)这里最后一个参数是Qt::DirectConnection——直接连接,意思是在信号发送者的线程中调用接收者的槽函数。默认的参数是Qt::AutoConnection,如果发送者和接收者不在同一个线程中,会使用Qt::QueuedDirection,槽函数的调用会在接收者所在的线程中执行;如果两个在同一个线程中,那就是Qt::DirectConnection,槽函数是立即在发送者的线程中调用的。这里指定为Qt::DirectConnection是必须的,首先因为调用的函数是非耗时的,且线程安全(修改的变量是atomic_bool),所以不会出现多线程读写同步的问题;另外,如果不使用Qt::DirectConnect,那么默认会使用Qt::QueuedConnection,停止按钮点击时,触发一个调用Worker::stop的事件,该事件需要work_thread进行处理,可work_thread此时正在进行耗时计算,只有当计算完毕之后,才会处理事件,调用stop,显然已经没有意义了,stop的目的就是在计算过程当中来随时终止计算。

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

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

相关文章

“打家劫舍”系列总结,偷不偷这个房间呢?(Java实现)

目录 前言 一、打家劫舍 ——>房子是线性的 1.1、dp定义 1.2、递推公式 1.3、初始化 1.4、遍历顺序 1.5、解题代码 二、打家劫舍II ——>房子是环型 2.1、分析 2.2、解题代码 三、打家劫舍III ——>房子是树形 3.1、dp含义 3.2、递推公式 3.3、解题代码…

【Trusted Firmware-A 移植】

Trusted Firmware-A 移植Trusted Firmware-A 简介步骤一、解压标准 tf-a 源码包,进入 tf-a 源码目录下&#xff1a;二、将 ST 官方补丁文件打到 tf-a 源码中&#xff1a;三、配置交叉编译工具链四、添加设备树文件五、编译源码六、固件烧写结果Trusted Firmware-A 简介 嵌入式…

Magisk工具使用指南

对于一般玩机用户,Magisk官方提供的发布版本即可满足要求,但对于高级开发者来说这远远不够,我们不仅仅是满足于使用,更要学会定制面具,最好的能完全理解面具的核心架构以便于自己也能写出来一套和面具差不多的工具,这才是我们研究面具最根本的原因所在。因为做移动安全,…

edp 基本信号-参数及命令

基本信号及概念通信双方及通道下图为edp规范中的总体框图。通过此框图我们可以了解到&#xff1a;交互的双方&#xff1a;1&#xff09;source device 即 显卡的显示控制部分2) sink device 即 显示屏 双方间的通道&#xff1a;1&#xff09; HPD 即热插拔&#xff0c;通过sink…

mysql之6中索引失效情况

对索引使用左或者左右模糊匹配 mysql> explain select * from user where name王五; -------------------------------------------------------------------------------------------- | id | select_type | table | type | possible_keys | key | key_len | ref …

2023.1.30---TF-A相关

完成TF-A源码的移植过程在tf-a源码目录下将补丁文件打到tf-a源码中2.在上级目录中的Makefile.sdk文件中&#xff0c;配置交叉编译工具链&#xff0c;找到CROSS_COMPILE将红色部分改为arm-linux-gnueabihf-3.在fds目录下添加设备树文件4.在上级目录中的Makefile.sdk文件中&#…

全世界游客访问最多的城市,重庆以5.9亿游客量排名第一

经过全面开放和“阳康”&#xff0c;旅游市场已经开始复苏。现在恰逢寒冬&#xff0c;海南等国内许多旅游胜地成为热门旅游目的地&#xff0c;泰国等国际旅游频频上热搜。旅游市场目前现状如何跟随《旅游市场数据报告》一起来了解吧。全国5A景区数量全国共有318个景区被评为AAA…

重温数据结构与算法之约瑟夫问题

文章目录前言一、暴力法二、动态规划三、实战3.1 力扣 1823. 找出游戏的获胜者3.2 洛谷 P1996 约瑟夫问题参考前言 约瑟夫问题&#xff0c;是一个计算机科学和数学中的问题&#xff0c;在计算机编程的算法中&#xff0c;类似问题又称为约瑟夫环&#xff0c;又称“丢手绢问题”…

K8s关键性概念图解

Kubernetes可以看做云原生时代的操作系统&#xff0c;统一管理下层的基础设施&#xff0c;如计算资源、网络资源、存储资源等等。将集群中存在的各种复杂关系抽象成各种API资源&#xff0c;以统一的方式暴露出各种接口&#xff0c;也便于未来的扩展以及开发团队根据自己的需要定…

JS创建ZIP文件,JSZip的使用

Hi I’m Shendi 最近编写压缩工具&#xff0c;需要使用js创建zip文件&#xff0c;使用 JSZip 插件 官网&#xff1a; https://stuk.github.io/jszip/ Github&#xff1a; https://github.com/Stuk/jszip https://sdpro.top/blog/html/article/1012.html 下载 NPM : npm inst…

论文笔记:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis

目录 文章摘要 1 Neural Radiance Field Scene Representation (基于神经辐射场的场景表示) 2 Volume Rendering with Radiance Fields (基于辐射场的体素渲染) 2.1 经典渲染方程 2.2 经典的体素渲染方法 2.3 基于分段采样近似的体素渲染方法 3 Optimizing a Neural Rad…

高通开发系列 - linux kernel启动阶段串口无打印采用LED点灯

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 问题背景kernel启动汇编探测kernel启动C函数阶段探测这篇文章之前请参考下:高通开发系列 - MSM8909指示灯操作 问题背景 最近在基于…

38. 外观数列

打卡!!!每日一题 今天给大家带来一道比较有意思的题目&#xff0c;先看看题目描述 题目描述&#xff1a; 题目示例&#xff1a; 大家题目读完可能还没太理解什么意思&#xff0c;我简单给大家翻译翻译&#xff1a; n&#xff1a;表示我们要计算多少次 每一次都是对前面一个…

详细介绍Sentence-BERT:使用连体BERT网络的句子嵌入

Sentence-BERT:Sentence Embeddings using Siamese BERT-Networks 使用连体BERT网络的句子嵌入 BERT和RoBERTa在诸如语义文本相似性&#xff08;STS&#xff09;的句子对回归任务上创造了新的最优的性能。然而&#xff0c;它要求将两个句子都输入网络&#xff0c;这导致了巨大的…

代码随想录--二叉树章节总结Part IV 完结篇

代码随想录–二叉树章节总结Part IV 完结篇&#x1f389; 1.Leetcode501 二叉树中的众数 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如…

大数据行业如何获取高薪岗位offer?

在互联网行业需要保持不断的学习。学习大数据先思考自身未来想往哪个方向发展&#xff0c;想要入门快、基础深厚&#xff0c;并且需求多应用广建议从JAVA开始学起&#xff0c;找到适合自己的学习方法。 大数据行业人才稀缺&#xff0c;据第三方统计2020年全国招收程序员394699…

mybatis-plus2

目录 一、乐观锁 二、乐观锁与悲观锁的区别 1.乐观锁和悲观锁的应用场景 三、条件查询构造器 四、分页查询 五、逻辑删除 六、在Mybatis-plus中使用xml配置 一、乐观锁 乐观锁插件 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/0d93c0/ 当要更新一条…

16. JSON解析

1. 什么是 JSON &#xff1f; JSON 指的是 JavaScript 对象表示法&#xff08;JavaScript Object Notation&#xff09;。 JSON 是轻量级的文本数据交换格式。 JSON 独立于语言&#xff1a;JSON 使用 Javascript语法来描述数据对象&#xff0c;但是 JSON 仍然独立于语言和平台…

Kettle基础操作

目录 Kettle基础操作 1 启动Kettle 2 创建本地资源库 3 基础操作 3.1 新建转换 3.2 新建作业 3.3 节点连接 4 导入/导出资源库 5 创建数据库连链接 Kettle基础操作 1 启动Kettle 前置环境&#xff1a;JDK 1.7以上、IE浏览器升级至IE10以上&#xff08;Kettle7.0以下…

Java——打家劫舍

题目链接 leetcode在线oj题——打家劫舍 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff…