QProgressDialog用法及结合QThread用法,四种线程使用

news2024/9/21 14:38:56

1 QProgressDialog概述

QProgressDialog类提供耗时操作的进度条。
进度对话框用于向用户指示操作将花费多长时间,并演示应用程序没有冻结。此外,QPorgressDialog还可以给用户一个中止操作的机会。
进度对话框的一个常见问题是很难知道何时使用它们;操作在不同的硬件上花费不同的时间。QProgressDialog为这个问题提供了一个解决方案:它估计操作将花费的时间(基于步骤的时间),并且仅在估计超过minimumDuration()(默认为4秒)时才显示它自己。
使用setMinimum()setMaximum()或构造函数设置操作中的“steps”数,并在操作进行时调用setValue()steps数可以任意选择。它可以是复制的文件数、接收的字节数、通过算法主循环的迭代次数,或者其他合适的单位。进度从setMinimum()设置的值开始,当使用setMaximum()设置的值作为参数调用setValue()时,进度对话框显示操作已经完成。
在操作结束时,对话框会自动重置并隐藏自己。使用setAutoReset()setAutoClose()来改变这种行为。
注意,如果设置了一个新的最大值(使用setMaximum()setRange()),它等于你的当前值(),无论如何对话框都不会关闭。

QProgressDialog progress;
progress.setMaximun(100);
Progress.setValue(100);

以上代码,对话框不会自动隐藏。
QProgressDialog有两种使用方式:模态和非模态。
与非模态QProgressDialog相比,模态QProgressDialog对于程序员来说更容易使用。在循环中执行操作,每隔一段时间调用setValue(),并使用wasCanceled()检查是否取消。
例如:

QProgressDialog progress("复制文件...", "中止", 0, numFiles, this);
      progress.setWindowModality(Qt::WindowModal);

      for (int i = 0; i < numFiles; i++) {
          progress.setValue(i);

          if (progress.wasCanceled())
              break;
          // 开始复制
	      // ......
      }
	   // 复制完成,将最大值设置给当前值,对话框自动隐藏,关闭
      progress.setValue(numFiles);

在这里插入图片描述

2 QProgressDialog常用函数

2.1 构造函数:

  • QProgressDialog(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()):创建一个默认的进度对话框,parent是对话框的父部件,f是对话框的窗口标志。
  • QProgressDialog(const QString &labelText, const QString &cancelButtonText, int minimum, int maximum, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()):创建一个带有文本标签、取消按钮和进度范围的进度对话框。labelText是标签的文本,cancelButtonText是取消按钮的文本,minimum和maximum指定了进度的范围。

2.2 成员函数:

  • void cancel():重置进度对话框,将wasCanceled()标记为true,直到进度对话框被重置。进度对话框将隐藏起来。
  • void canceled():在点击取消按钮时发射的信号,默认与cancel()槽连接。
  • void open(QObject *receiver, const char *member):打开对话框,并将其canceled()信号连接到receiver对象的member槽上。
  • void reset():重置进度对话框,如果autoClose()为true,则对话框将隐藏。
  • void setBar(QProgressBar *bar):设置进度条部件。
  • void setCancelButton(QPushButton *cancelButton):设置取消按钮部件。
  • void setCancelButtonText(const QString &cancelButtonText):设置取消按钮的文本。
  • void setLabel(QLabel *label):设置标签部件。
  • void setRange(int minimum, int maximum):设置进度范围。
  • QSize sizeHint() const:返回适合对话框内容的大小。

2.3 常用方法示例代码

CustomProgress::CustomProgress(QWidget *parent) : QProgressDialog(parent)
{
    // 设置窗体Flags, 对话框 | 只有关闭按钮,无问号
    this->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
    // 设置取消按钮文本
    this->setCancelButtonText("取消");


    // 设置进度条区间,等同分别设置最小值  和  最大值
    setRange(0, 100);
    // 设置最小值
    setMinimum(0);
    // 设置最大值
    setMaximum(100);

    // 设置当前值
    setValue(0);

    // 设置文本,一般在进度条上方显示
    setLabelText("helloworld");
    
    // 设置自动关闭,当reset()时,对话框自动关闭,默认为true
    setAutoClose(true);
    // 设置自动重置,当reset()或当前值 == 最大值时,重置
    setAutoReset(true);


    connect(this, &CustomProgress::canceled, this, &CustomProgress::cancel);

    // 设置对话框窗体标题
    this->setWindowTitle("等待...");
}

3 线程Qthread

当在主线程里,进行耗时操作,然后加载进度对话框时,会发现,对话框进度条会卡死不动,然后耗时操作结束,对话框进度条直接关闭,界面感官不友好。
因此需要将耗时操作放到线程内操作,主线程就进行进度显示。界面也不会卡死。

QThread类提供了一种独立于平台的方式来管理线程。
QThread对象管理程序中的一个控制线程。QThreadsrun()中开始执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内运行Qt事件循环。

此外,还可以通过使用QObject::moveToThread()将工作对象移动到线程中来使用它们。

下面是四种线程使用方式与进度框相结合,模拟处理耗时操作,主界面显示进度。

3.1 继承QThread,重写run()方法

.h

class C_Thread : public QThread
{
    Q_OBJECT
public:
    explicit C_Thread(int nMax, QObject *parent = nullptr);

    virtual void run() override;

signals:
    void emit_sendValue(int nValue);

private:
    int     m_nMax;
};

.cpp

#include "Thread.h"

C_Thread::C_Thread(int nMax, QObject *parent) : QThread(parent), m_nMax(nMax)
{

}

void C_Thread::run()
{
    int i = 0;
    while (i < m_nMax) {
        msleep(100);
        ++i;
        emit emit_sendValue(i);
    }
}

当进行start()时,自动调用run(),每过100ms,发送一个数据,主界面进行显示

3.2 继承QObject,之后添加到线程moveToThread(),使用信号和槽方式

需要将进行耗时操作的类,移动到线程中,之后以信号和槽的方式和进度框进行交互
.h

class C_ThreadObject : public QObject
{
    Q_OBJECT
public:
    explicit C_ThreadObject(int nMax, QObject *parent = nullptr);

signals:
    void emit_sendValue(int nValue);

public slots:
    void slot_dealValue();

private:
    int     m_nMax;
};

.cpp

C_ThreadObject::C_ThreadObject(int nMax, QObject *parent) : QObject(parent), m_nMax(nMax)
{

}

void C_ThreadObject::slot_dealValue()
{
    int i = 0;
    while (i < m_nMax) {
        QThread::msleep(100);
        ++i;
        emit emit_sendValue(i);
    }
}

3.3 继承QRunnable

重写run(),然后通过线程池调用
.h

class C_ThreadRunnable :public QObject, public QRunnable
{
    Q_OBJECT
public:
    explicit C_ThreadRunnable(int nMax);

signals:
    void emit_sendValue(int nValue);

public slots:

protected:
    virtual void run() override;

private:
    int m_nMax;
};

.cpp

C_ThreadRunnable::C_ThreadRunnable(int nMax) : m_nMax(nMax)
{

}

void C_ThreadRunnable::run()
{
    int i = 0;
    while (i < m_nMax) {
        QThread::msleep(100);
        ++i;
        emit emit_sendValue(i);
    }
}

3.4 使用QtConcurrent模块

Qt Concurrent模块扩展了Qt Core模块中的基本线程支持,简化了可以在所有可用CPU内核上并行执行的代码开发。
.h

void MainWindow::dealValue()
{
    int i = 0;
    while (i < m_nMax) {
        QThread::msleep(100);
        ++i;
        emit emit_sendValue(i);
    }
}

.cpp

QtConcurrent::run(this, &MainWindow::dealValue);

3.5 主线程调用

创建各个线程对象,然后进行模拟耗时操作,进度框显示进度
如果在构造中new过QProgressDialog对象,默认4秒后,会自动显示,可以调用其close()方法,不用显示。
.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    void dealValue();

signals:
    void emit_start();

    void emit_sendValue(int nValue);

private slots:
    void on_btn_TimeConsumingOperation_clicked();

private:
    Ui::MainWindow *ui;
    int                   m_nMax;

    C_DlgProgress*        m_pDlgProgress;
    C_Thread*             m_pTread;
    C_ThreadRunnable*     m_pThreadRunnable;

    C_ThreadObject*       m_pThreadObject;
    QThread*              m_pThreadUsedObject;
};

.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QThreadPool>
#include <QtConcurrent>
#include <QDebug>


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

    m_nMax = 20;

    m_pDlgProgress = new C_DlgProgress(this);
    m_pDlgProgress->setRange(0, m_nMax);

    // 1. 继承QThread
    m_pTread = new C_Thread(m_nMax, this);
    connect(m_pTread, &C_Thread::emit_sendValue, this, [=](int nValue){
        m_pDlgProgress->setValue(nValue);
    });

    // 2. 继承QRunnable
    m_pThreadRunnable = new C_ThreadRunnable(m_nMax);
    connect(m_pThreadRunnable, &C_ThreadRunnable::emit_sendValue, this, [=](int nValue){
        m_pDlgProgress->setValue(nValue);
    });

    // 3. 继承QObject
    m_pThreadObject = new C_ThreadObject(m_nMax);
    connect(this, &MainWindow::emit_start, m_pThreadObject, &C_ThreadObject::slot_dealValue);
    connect(m_pThreadObject, &C_ThreadObject::emit_sendValue, this, [=](int nValue){
        m_pDlgProgress->setValue(nValue);
    });
    m_pThreadUsedObject = new QThread(this);
    m_pThreadObject->moveToThread(m_pThreadUsedObject);
    m_pThreadUsedObject->start();

    // 0. 在主线程处理耗时操作
    connect(this, &MainWindow::emit_sendValue, this, [=](int nValue){
        m_pDlgProgress->setValue(nValue);
    });
}

MainWindow::~MainWindow()
{
    if(m_pThreadUsedObject)
    {
        m_pThreadUsedObject->quit();
        m_pThreadUsedObject->wait();
    }

    delete ui;
}

void MainWindow::dealValue()
{
    int i = 0;
    while (i < m_nMax) {
        QThread::msleep(100);
        ++i;
        emit emit_sendValue(i);
    }
}

void MainWindow::on_btn_TimeConsumingOperation_clicked()
{
    m_pDlgProgress->show();
    // 0. 在主线程模拟处理耗时操作,界面卡死
    //    int i = 0;
    //    while (i < m_nMax) {
    //        QThread::msleep(100);
    //        ++i;
    //        emit emit_sendValue(i);
    //    }

    /*********** 使用哪个,打开哪个注释  ***********/

    // 1. 继承QThread
    // m_pTread->start();

    // 2. 继承QRunnable
    // QThreadPool::globalInstance()->start(m_pThreadRunnable);

    // 3. 继承QObject
    // emit emit_start();

    // 4. 使用QtConcurrent模块
    // QtConcurrent::run(this, &MainWindow::dealValue);
}

3.6 结果

主界面显示:
在这里插入图片描述

点击耗时操作
在这里插入图片描述
当进度走完,进度框关闭。

4 完整示例连接

链接: https://download.csdn.net/download/MrHHHHHH/88692241?spm=1001.2014.3001.5501

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

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

相关文章

HTTP 错误 401.3 - Unauthorized 由于Web服务器上此资源的访问控制列表(ACL)配置或加密设置。

用IIS 发布网站&#xff0c;不能访问且出现错误&#xff1a; HTTP 错误 401.3 - Unauthorized 由于Web服务器上此资源的访问控制列表(ACL)配置或加密设置。您无权查看此目录或页面 解决办法&#xff1a; 1.打开IIS界面&#xff0c;选中发布的网站&#xff0c;右键—>编辑…

【C语言】Linux socket 编程

一、Socket 通信过程 在 Linux 系统中&#xff0c;socket 是一种特殊的文件描述符&#xff0c;用于在网络中的不同主机间或者同一台主机中的不同进程间进行双向通信。它是通信链路的端点&#xff0c;可以看作是网络通信的接口。Socket 通信过程主要分为以下几个步骤&#xff1a…

canvas绘制直角梯形(向右)

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

PTA QQ帐户的申请与登陆

QQ帐户的申请与登陆 分数 25 全屏浏览题目 作者 DS课程组 单位 浙江大学 实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是&#xff1a;据说现在的QQ号码已经有10位数了。 输入格式: 输入首先给出一个正整数N&#xff08;≤105&#xff09;&#xff0c;随后给出N行…

微服务-Gateway

案例搭建 官网地址 父Pom <com.alibaba.cloud.version>2.2.8.RELEASE</com.alibaba.cloud.version> <com.cloud.version>Hoxton.SR12</com.cloud.version> <com.dubbo.version>2.2.7.RELEASE</com.dubbo.version> <dependencyManagem…

Python基础-05(输出输入、if、if else和elif)

文章目录 前言一、输出&#xff08;print()&#xff09;和输入&#xff08;input()&#xff09;二、if、if else、elif1.if2.if else3.关于输入input的默认值4.elif 前言 今天复习一些非常基础的内容&#xff0c;以及if、if else和elif语句 一、输出&#xff08;print()&…

【vue/uniapp】pdf.js 在一些型号的手机上不显示

引入&#xff1a; uniapp 项目通过 pdf.js 来在线浏览 pdf 链接&#xff0c;在微信小程序中都显示正常&#xff0c;但是通过 app 跳转小程序&#xff0c;在苹果、小米显示正常&#xff0c;但是华为和 oppo 就不显示&#xff0c;可以通过降 pdf.js 的版本来解决这个问题。 解决&…

1.3 力扣二叉树中等题

题目一&#xff1a; 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&…

python flask图书管理系统带文档

python flask图书管理系统带文档。功能&#xff1a;登录&#xff0c;图书的增删改查&#xff0c;读者管理&#xff0c;借阅记录&#xff0c;有文档。 技术&#xff1a;python3,flask,mysql,html。 包含源码数据库文件文档。 源码下载地址&#xff1a; https://download.csd…

Calibre PEX Hspice Netlist提取步骤(数模芯片提取spice netlist流程)

在数模混合芯片中&#xff0c;通常模拟需要数字模块通过calibre工具来提取Hspice netlist用于功耗仿真。注意这里的spice netlist和做Calibre的spice netlist是不太一样的。 另外在做calibre pex时需要确保当前的design LVS已经pass。否则功耗仿真可能会不准。 Calibre LVS常…

Z-score 因子的深入思考

最新&#xff08;2024 年 1 月&#xff09;出版的 SC 技术分析&#xff08;Techical Analysis of Stock & Commodities&#xff09;的第 4 条文章给到了 Z-score&#xff0c;原文标题为《Z-score: How to use it in Trading》。今天的笔记&#xff0c;就借此机会&#xff0…

在日常工作中如何保障服务器的安全?

服务器在日常工作中具有重要的作用。它是网络的核心组成部分&#xff0c;承担着提供信息和服务的任务。 1.服务器为各种应用提供数据存储和处理服务&#xff0c;支持电子邮件、网页浏览、文件下载等服务&#xff0c;为用户提供高效、安全、可靠的网络访问。 2.服务器承载着各…

uni-app中实现元素拖动

uni-app中实现元素拖动 1、代码示例 <template><movable-area class"music-layout"><movable-view class"img-layout" :x"x" :y"y" direction"all"><img :src"musicDetail.bgUrl" :class&…

Linux mcd命令教程:如何在MS-DOS文件系统中切换工作目录(附实例教程和注意事项)

Linux mcd命令介绍 mcd是mtools工具的指令&#xff0c;它用于在MS-DOS文件系统中切换工作目录。如果不加任何参数&#xff0c;它将显示当前所在的磁盘和工作目录。 Linux mcd命令适用的Linux版本 mcd命令在所有主流的Linux发行版中都可以使用&#xff0c;包括但不限于Ubuntu…

Canvas保姆级教程----深入解析HTML5 Canvas工作原理和常用方法

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

01、Kafka ------ 下载、安装 ZooKeeper 和 Kafka

目录 Kafka是什么&#xff1f;安装 ZooKeeper下载安装启动 zookeeper 服务器端启动 zookeeper 的命令行客户端工具 安装 Kafka下载安装启动 Kafka 服务器 Kafka是什么&#xff1f; RabbitMQ的性能比ActiveMQ的性能有显著提升。 Kafka的性能比RabbitMQ的性能又有显著提升。 K…

ngrok-内网穿透

一、访问官网下载相关的内容 Download (ngrok.com) linux或者windows可供选择&#xff0c;主要在于你的项目跑在什么地方 选择下载 二、获取Authtoken 点击右上角登录&#xff0c;没有号用谷歌账号登录即可跳转 三、在Windows进行内网穿透 下载打开 打开 运行在命令行中&am…

【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐--…

【Spring】19 AOP介绍及实例详解

文章目录 1. 定义1&#xff09;什么意思呢&#xff1f;2&#xff09;如何解决呢&#xff1f; 2. 基本概念1&#xff09;切面&#xff08;Aspect&#xff09;2&#xff09;切点&#xff08;Pointcut&#xff09;3&#xff09;通知&#xff08;Advice&#xff09;4&#xff09;连…

【python入门】day17:模块化编程、math库常见函数

什么叫模块 模块的导入 导入所有&#xff1a;import 模块名称 导入指定&#xff1a;from 模块名称 import 函数/变量/类 python的math库 什么是math库 Python的math库是Python的内建库之一&#xff0c;它提供了许多数学函数&#xff0c;包括三角函数、对数函数、幂函数等&a…