Qt 进度条

本文介绍了如何在Qt环境中创建一个自定义的进度条控件,该控件具备动态值变化、警戒值设定、颜色变化等功能,并通过重写QLabel的paintEvent事件来实现动态效果。使用VS2013和Qt5.5为开发环境,通过继承QLabel并定时刷新值来展示进度条的实时状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

  有时我们需要在表格(QTableWidget)、树状栏(QTreeWidget)中直观显示任务进度或消耗百分比,达到报表显示的形式,可通过重写QLabel的方式实现。

  1、进度条控件功能

    1)可设置值动态变化

    2)可设置警戒值

    3)可设置正常颜色和报警颜色

    4)可设置边框渐变颜色

    5)可设置变化时每次移动的步长

    6)可设置错误时显示错误描述

    7)可设置显示值保留小数的位数

    8)可设置边框圆角角度/背景进度圆角角度/头部圆角角度    
  2、实现效果

二、实现过程

  1、运行环境Qt5.5 VS2013

  2、继承QLabel重写ProgressLabel控件

原文链接:Qt 进度条-QT开发中文网

   /***********************************************************************
   功能:进度控件
   1、可设置值动态变化
   2、可设置警戒值
   3、可设置正常颜色和报警颜色
   4、可设置边框渐变颜色
   5、可设置变化时每次移动的步长
   6、可设置错误时显示错误描述
  6、可设置显示值保留小数的位数
  8、可设置边框圆角角度/背景进度圆角角度/头部圆角角度
  ************************************************************************/
  
  #ifndef PROGRESS_LABEL_H
  #define PROGRESS_LABEL_H
  
  #include <QLabel>
  #include <QWidget>
  
  #ifdef Plugin
  #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
  #include <QtDesigner/QDesignerExportWidget>
  #else
  #include <QtUiPlugin/QDesignerExportWidget>
  #endif
  
  class QDESIGNER_WIDGET_EXPORT ProgressLabel : public QLabel
  #else
  class ProgressLabel : public QLabel
  #endif
  {
      Q_OBJECT    
      Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
      Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
      Q_PROPERTY(double value READ getValue WRITE setValue)
      Q_PROPERTY(double alarmValue READ getAlarmValue WRITE setAlarmValue)
  
      Q_PROPERTY(double step READ getStep WRITE setStep)
      Q_PROPERTY(int decimals READ getDecimals WRITE setDecimals)
      Q_PROPERTY(int borderRadius RE
<think>我们讨论的是Qt中的进度条(QProgressBar)。Qt进度条用于显示任务的进度,可以水平或垂直显示,也可以显示文本或仅显示进度条。我们可以自定义进度条的样式,设置范围、值,以及处理进度更新等。 以下是一个简单的示例,展示如何使用QProgressBar: 1. 创建进度条并设置范围(默认为0到99) 2. 更新进度条的值 3. 设置文本显示格式 4. 自定义样式 此外,我们还可以结合QProgressDialog来创建一个带有取消按钮的进度对话框。 下面是一个完整的示例代码,包括一个自定义样式的进度条和一个进度对话框的使用。 ```cpp #include <QApplication> #include <QProgressBar> #include <QProgressDialog> #include <QPushButton> #include <QVBoxLayout> #include <QWidget> #include <QTimer> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建一个主窗口 QWidget window; window.setWindowTitle("Qt Progress Bar Example"); window.resize(400, 200); // 创建垂直布局 QVBoxLayout *layout = new QVBoxLayout(&window); // 示例1:基本进度条 QProgressBar *progressBar = new QProgressBar(&window); progressBar->setRange(0, 100); // 设置范围 progressBar->setValue(0); // 设置初始值 progressBar->setTextVisible(true); // 显示文本 progressBar->setFormat("%p%"); // 显示百分比 // 示例2:自定义样式的进度条 QProgressBar *styledProgressBar = new QProgressBar(&window); styledProgressBar->setRange(0, 100); styledProgressBar->setValue(0); styledProgressBar->setTextVisible(true); styledProgressBar->setFormat("Processing: %p%"); // 自定义样式 styledProgressBar->setStyleSheet( "QProgressBar {" " border: 2px solid grey;" " border-radius: 5px;" " background-color: #FFFFFF;" " text-align: center;" "}" "QProgressBar::chunk {" " background-color: #05B8CC;" " width: 10px;" " margin: 0.5px;" "}" ); // 按钮用于启动进度 QPushButton *startButton = new QPushButton("Start Progress", &window); layout->addWidget(progressBar); layout->addWidget(styledProgressBar); layout->addWidget(startButton); // 使用QTimer模拟进度更新 QTimer *timer = new QTimer(&window); int progress = 0; QObject::connect(timer, &QTimer::timeout, [&]() { progress++; progressBar->setValue(progress); styledProgressBar->setValue(progress); if (progress > 100) { timer->stop(); progress = 0; } }); // 点击按钮开始进度 QObject::connect(startButton, &QPushButton::clicked, [&]() { progress = 0; timer->start(50); // 每50毫秒更新一次 }); // 示例3:使用QProgressDialog QPushButton *dialogButton = new QPushButton("Show Progress Dialog", &window); layout->addWidget(dialogButton); QObject::connect(dialogButton, &QPushButton::clicked, [&]() { // 创建进度对话框 QProgressDialog progressDialog("Processing...", "Cancel", 0, 100, &window); progressDialog.setWindowTitle("Progress Dialog"); progressDialog.setWindowModality(Qt::WindowModal); progressDialog.setMinimumDuration(0); // 立即显示 // 模拟进度 for (int i = 0; i <= 100; ++i) { progressDialog.setValue(i); QApplication::processEvents(); // 处理事件,使界面能够响应 if (progressDialog.wasCanceled()) { break; } // 模拟耗时操作 QThread::msleep(30); } progressDialog.setValue(100); }); window.show(); return app.exec(); } ``` ### 代码解释: 1. **基本进度条(QProgressBar)**: - 创建了一个标准的进度条,设置范围0-100,初始值为0。 - 通过`setFormat`设置显示格式,`%p%`表示显示百分比。 2. **自定义样式的进度条**: - 使用`setStyleSheet`方法自定义进度条的外观。 - 这里设置了边框、圆角、背景色,以及进度块(chunk)的颜色和边距。 3. **QTimer模拟进度更新**: - 点击按钮后,启动一个定时器,每50毫秒增加进度值,并更新两个进度条。 4. **QProgressDialog**: - 点击另一个按钮会显示一个进度对话框。 - 使用循环模拟进度,每次循环更新对话框的进度值。 - 调用`QApplication::processEvents()`确保界面响应,特别是处理取消按钮的点击。 - 如果用户点击取消,则中断循环。 ### 注意事项: - 在进度对话框中执行耗时操作时,要确保调用`processEvents`,否则界面会卡住,无法响应用户操作(如取消)。 - 自定义样式时,可以使用Qt样式表(类似CSS)来设置进度条的外观,包括边框、背景、进度块等。 ### 相关问题: §§相关问题§§: 1. 如何在Qt中创建一个垂直的进度条? 2. QProgressBar的样式表有哪些可自定义的选项? 3. 如何实现一个不确定进度的进度条(如忙碌指示)? 4. 在多线程任务中如何安全地更新进度条?</think># Qt 进度条详解与高级实现 在 Qt 中,进度条是展示任务进度的核心组件。我将详细介绍 QProgressBar 的用法,并提供高级自定义实现方案。 ## 基础 QProgressBar 使用 ```cpp #include <QProgressBar> #include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QTimer> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建主窗口 QWidget window; window.setWindowTitle("Qt 进度条示例"); window.resize(400, 200); // 创建进度条 QProgressBar *progressBar = new QProgressBar(&window); progressBar->setRange(0, 100); // 设置范围 progressBar->setValue(0); // 初始值 progressBar->setTextVisible(true); // 显示文本 progressBar->setFormat("处理中: %p%"); // 自定义文本格式 // 创建布局 QVBoxLayout *layout = new QVBoxLayout(&window); layout->addWidget(progressBar); // 使用定时器模拟进度更新 QTimer *timer = new QTimer(&window); int progress = 0; QObject::connect(timer, &QTimer::timeout, [&]() { progress++; progressBar->setValue(progress); if (progress >= 100) { timer->stop(); progressBar->setFormat("完成! 耗时: 5秒"); } }); timer->start(50); // 每50毫秒更新一次 window.show(); return app.exec(); } ``` ## 高级自定义进度条实现 ### 1. 圆角渐变进度条 ```cpp #include <QProgressBar> #include <QPainter> #include <QStyleOption> class RoundedGradientProgressBar : public QProgressBar { Q_OBJECT public: explicit RoundedGradientProgressBar(QWidget *parent = nullptr) : QProgressBar(parent) { setTextVisible(false); } protected: void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 绘制背景 painter.setPen(Qt::NoPen); painter.setBrush(QColor(230, 230, 230)); painter.drawRoundedRect(rect(), 8, 8); // 计算进度宽度 double progress = static_cast<double>(value() - minimum()) / (maximum() - minimum()); int progressWidth = width() * progress; if (progressWidth > 0) { // 创建渐变 QLinearGradient gradient(0, 0, progressWidth, 0); gradient.setColorAt(0, QColor("#3498db")); gradient.setColorAt(1, QColor("#2ecc71")); // 绘制进度条 painter.setBrush(gradient); painter.drawRoundedRect(QRect(0, 0, progressWidth, height()), 8, 8); // 绘制高光效果 painter.setBrush(Qt::NoBrush); painter.setPen(QPen(QColor(255, 255, 255, 150), 1)); painter.drawRoundedRect(QRect(0, 0, progressWidth, height()), 8, 8); } // 绘制文本 painter.setPen(Qt::black); painter.drawText(rect(), Qt::AlignCenter, text()); } }; ``` ### 2. 多段式进度条 ```cpp #include <QProgressBar> #include <QPainter> #include <QVector> class MultiSegmentProgressBar : public QProgressBar { Q_OBJECT public: explicit MultiSegmentProgressBar(QWidget *parent = nullptr) : QProgressBar(parent) { setRange(0, 100); // 添加分段配置:位置,颜色 segments << Segment{0, QColor("#e74c3c")} // 0-25% 红色 << Segment{25, QColor("#f39c12")} // 25-50% 橙色 << Segment{50, QColor("#3498db")} // 50-75% 蓝色 << Segment{75, QColor("#2ecc71")}; // 75-100% 绿色 } struct Segment { int position; QColor color; }; void setSegments(const QVector<Segment> &newSegments) { segments = newSegments; update(); } protected: void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 绘制背景 painter.fillRect(rect(), QColor(240, 240, 240)); // 计算当前进度 double progress = static_cast<double>(value() - minimum()) / (maximum() - minimum()); int progressWidth = width() * progress; // 绘制分段进度 int prevPos = 0; for (int i = 0; i < segments.size(); i++) { int segmentEnd = qMin(static_cast<int>(segments[i].position * width() / 100.0), progressWidth); if (segmentEnd > prevPos) { painter.fillRect(prevPos, 0, segmentEnd - prevPos, height(), segments[i].color); prevPos = segmentEnd; } } // 绘制分隔线 painter.setPen(QPen(Qt::white, 2)); for (const Segment &seg : segments) { int pos = seg.position * width() / 100.0; if (pos > 0 && pos < width()) { painter.drawLine(pos, 0, pos, height()); } } // 绘制文本 painter.setPen(Qt::black); painter.drawText(rect(), Qt::AlignCenter, text()); } private: QVector<Segment> segments; }; ``` ### 3. 动画进度条 ```cpp #include <QProgressBar> #include <QPainter> #include <QPropertyAnimation> class AnimatedProgressBar : public QProgressBar { Q_OBJECT Q_PROPERTY(qreal glowPosition READ glowPosition WRITE setGlowPosition) public: explicit AnimatedProgressBar(QWidget *parent = nullptr) : QProgressBar(parent), m_glowPosition(0) { // 创建动画效果 QPropertyAnimation *animation = new QPropertyAnimation(this, "glowPosition"); animation->setDuration(2000); animation->setStartValue(0); animation->setEndValue(1); animation->setLoopCount(-1); // 无限循环 animation->start(); } qreal glowPosition() const { return m_glowPosition; } void setGlowPosition(qreal pos) { m_glowPosition = pos; update(); } protected: void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 绘制背景 painter.fillRect(rect(), QColor(240, 240, 240)); // 计算进度宽度 double progress = static_cast<double>(value() - minimum()) / (maximum() - minimum()); int progressWidth = width() * progress; if (progressWidth > 0) { // 绘制主进度条 QLinearGradient mainGradient(0, 0, progressWidth, 0); mainGradient.setColorAt(0, QColor(52, 152, 219)); mainGradient.setColorAt(1, QColor(41, 128, 185)); painter.fillRect(QRect(0, 0, progressWidth, height()), mainGradient); // 绘制发光效果 if (isEnabled()) { int glowWidth = 30; int glowPos = m_glowPosition * (progressWidth + glowWidth) - glowWidth; QLinearGradient glowGradient(0, 0, glowWidth, 0); glowGradient.setColorAt(0, QColor(255, 255, 255, 0)); glowGradient.setColorAt(0.5, QColor(255, 255, 255, 150)); glowGradient.setColorAt(1, QColor(255, 255, 255, 0)); painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.fillRect(QRect(glowPos, 0, glowWidth, height()), glowGradient); } } // 绘制文本 painter.setPen(Qt::black); painter.drawText(rect(), Qt::AlignCenter, text()); } private: qreal m_glowPosition; }; ``` ## 进度条最佳实践 ### 1. 多线程进度更新 ```cpp #include <QProgressBar> #include <QThread> #include <QFuture> #include <QtConcurrent> class TaskWorker : public QObject { Q_OBJECT public: explicit TaskWorker(QObject *parent = nullptr) : QObject(parent) {} public slots: void startTask() { for (int i = 0; i <= 100; i++) { QThread::msleep(50); // 模拟耗时操作 emit progressChanged(i); } emit taskCompleted(); } signals: void progressChanged(int value); void taskCompleted(); }; // 在UI类中使用 class MainWindow : public QWidget { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QWidget(parent) { // 创建UI组件 QProgressBar *progressBar = new QProgressBar(this); progressBar->setRange(0, 100); // 创建任务线程 QThread *workerThread = new QThread(this); TaskWorker *worker = new TaskWorker(); worker->moveToThread(workerThread); // 连接信号 connect(worker, &TaskWorker::progressChanged, progressBar, &QProgressBar::setValue); connect(worker, &TaskWorker::taskCompleted, [=]() { workerThread->quit(); worker->deleteLater(); }); connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater); // 启动线程 QPushButton *startButton = new QPushButton("开始任务", this); connect(startButton, &QPushButton::clicked, [=]() { startButton->setEnabled(false); workerThread->start(); QMetaObject::invokeMethod(worker, "startTask", Qt::QueuedConnection); }); // 布局 QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(progressBar); layout->addWidget(startButton); } }; ``` ### 2. 进度条样式定制 ```cpp // 设置进度条样式 progressBar->setStyleSheet( "QProgressBar {" " border: 2px solid #b0b0b0;" " border-radius: 5px;" " background: #f0f0f0;" " text-align: center;" " height: 25px;" "}" "QProgressBar::chunk {" " background: qlineargradient(x1:0, y1:0, x2:1, y2:0," " stop:0 #3498db, stop:0.5 #2ecc71, stop:1 #e74c3c);" " border-radius: 3px;" " margin: 1px;" "}" ); ``` ## 进度条使用场景 1. **文件操作**:文件复制、下载、上传 2. **数据处理**:大数据集处理、图像处理 3. **安装过程**:软件安装、更新 4. **渲染过程**:3D渲染、视频导出 5. **复杂计算**:科学计算、模拟 ## 进度条设计原则 1. **准确性**:进度应反映真实进度 2. **及时性**:进度更新频率应适中(100-500ms) 3. **可中断性**:提供取消操作 4. **信息丰富**:显示进度百分比、剩余时间 5. **视觉反馈**:使用动画增强用户体验
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值