首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【从零开始的Qt开发指南】(九)Qt 常用控件之显示类控件(下):ProgressBar 与 CalendarWidget 实战进阶

【从零开始的Qt开发指南】(九)Qt 常用控件之显示类控件(下):ProgressBar 与 CalendarWidget 实战进阶

作者头像
_OP_CHEN
发布2026-01-14 11:35:15
发布2026-01-14 11:35:15
510
举报
文章被收录于专栏:C++C++

前言

在 Qt GUI 开发中,显示类控件不仅要承担信息展示的基础职责,还需满足动态反馈交互选择的核心需求。ProgressBar(进度条)以直观的可视化方式呈现任务进度,是文件上传、数据加载等场景的必备控件;CalendarWidget(日历控件)则为日期选择提供了标准化界面,广泛应用于日程管理、数据筛选等功能中。本文将基于 Qt 5.14 版本,从核心属性、实战案例到进阶技巧,全面拆解这两个控件的使用方法,带你解锁显示类控件的高级玩法!下面就让我们正式开始吧!


一、ProgressBar 控件:任务进度的可视化神器

QProgressBar 是 Qt 中用于展示任务进度的核心控件,它通过填充的进度条直观反映任务完成比例,支持自定义进度样式、显示格式和方向,能极大提升用户对长时间任务的感知体验。无论是简单的倒计时进度,还是复杂的文件传输进度展示,ProgressBar 都能轻松胜任。

1.1 ProgressBar 核心属性解析

ProgressBar 的属性围绕进度展示和外观样式展开,以下是最常用的核心属性,结合实用场景帮你快速理解:

属性名

功能说明

取值 / 类型

实用场景

minimum

进度条最小值

int(默认 0)

任务起始点(如文件下载从 0 开始)

maximum

进度条最大值

int(默认 100)

任务终点(如 100% 完成)

value

进度条当前值

int(默认 0)

实时更新任务进度

alignment

进度文本对齐方式

Qt::AlignLeft/AlignCenter/AlignRight 等

优化进度文本显示位置

textVisible

是否显示进度文本

bool(默认 true)

简洁界面可隐藏文本

orientation

进度条方向

Qt::Horizontal(水平,默认)/Qt::Vertical(垂直)

水平适用于顶部 / 底部进度,垂直适用于侧边栏

invertAppearance

是否反向增长

bool(默认 false)

特殊场景下进度从右向左 / 从下向上增长

textDirection

进度文本方向

Qt::LeftToRight/Qt::RightToLeft

适配不同语言排版需求

format

进度文本格式

字符串(支持 % p/% v/% m/% t 占位符)

自定义进度显示(如 “50%”“已完成 50/100”)

其中,format属性的占位符功能非常实用,四个核心占位符的含义如下:

  • %p:显示百分比(0-100),如 “50%”;
  • %v:显示当前进度值,如 “50”;
  • %m:显示剩余时间(毫秒级,需结合定时器计算);
  • %t:显示总时间(毫秒级,需结合定时器计算)。

1.2 基础用法:快速实现进度条展示

ProgressBar 的基础用法非常简洁,通过设置minimummaximumvalue三个核心属性,即可实现进度展示。以下是两种常见的基础场景示例:

1.2.1 静态进度展示(固定进度值)

适用于展示已知进度的场景(如操作完成度提示):

代码语言:javascript
复制
#include "widget.h"
#include <QProgressBar>
#include <QLabel>
#include <QVBoxLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("ProgressBar基础用法");
    
    // 创建布局管理器(用于控件排版)
    QVBoxLayout *layout = new QVBoxLayout(this);
    
    // 创建提示标签
    QLabel *tipLabel = new QLabel("任务完成进度:", this);
    layout->addWidget(tipLabel);
    
    // 创建进度条
    QProgressBar *staticProgress = new QProgressBar(this);
    staticProgress->setMinimum(0);       // 最小值0
    staticProgress->setMaximum(100);     // 最大值100
    staticProgress->setValue(68);        // 当前进度68%
    staticProgress->setAlignment(Qt::AlignCenter); // 文本居中
    staticProgress->setFormat("已完成 %p%"); // 显示格式:已完成 68%
    layout->addWidget(staticProgress);
    
    // 添加垂直间距,优化界面
    layout->addSpacing(20);
    
    // 创建垂直进度条(演示方向属性)
    QLabel *verticalTip = new QLabel("垂直进度条演示:", this);
    layout->addWidget(verticalTip);
    
    QProgressBar *verticalProgress = new QProgressBar(this);
    verticalProgress->setOrientation(Qt::Vertical); // 垂直方向
    verticalProgress->setMinimum(0);
    verticalProgress->setMaximum(50);
    verticalProgress->setValue(35);
    verticalProgress->setFormat("%v/%m"); // 显示格式:35/50
    verticalProgress->setFixedHeight(150); // 固定高度,便于展示
    layout->addWidget(verticalProgress, 0, Qt::AlignCenter); // 居中对齐
}

运行程序后,可看到水平进度条显示 “已完成 68%”,垂直进度条显示 “35/50”,能直观展示不同方向和格式的进度效果。

1.2.2 动态进度展示(结合定时器)

适用于展示实时变化的进度(如文件下载、数据加载),结合 Qt 的 QTimer 控件可实现进度自动增长。

先在.ui文件中拖入ProgressBar控件:

编辑代码:

代码语言:javascript
复制
#include "widget.h"
#include "ui_widget.h"

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

    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Widget::handle);

    //启动定时器
    timer->start(100);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handle()
{
    //获取进度条的当前数值
    int value = ui->progressBar->value();
    if(value >= 100)
    {
        //进度条满了,就可以停止定时器了
        timer->stop();
        return;
    }
    ui->progressBar->setValue(value + 1);
}

运行程序后,进度条会从 0% 自动增长到 100%,进度文本实时显示 “XX%”,完成后提示 “下100%”,完美模拟了进度反馈。

1.3 样式自定义:打造个性化进度条

默认的 ProgressBar 样式较为朴素,通过 Qt Style Sheet(QSS)可自定义进度条的颜色、边框、圆角等样式,让界面更具设计感。我们可以通过QSS设置进度条的颜色为红色。

首先我们在空间的属性界面找到Style Sheet选项:

点击右侧的“...”进入QSS编辑页面,并输入如下的代码:

点击“OK”后运行程序,可以观察到进度条变为了红色:

当然,我们也可以通过类似的代码设置进度条为其他更加复杂的样式,大家可以在日后使用Qt时自行摸索。

1.4 ProgressBar 常见问题与避坑指南

在使用 ProgressBar 的过程中,容易遇到一些细节问题,这里总结了高频问题及解决方案:

问题 1:进度条不更新或更新卡顿

  • 原因 1:在主线程中执行耗时操作(如大文件读取),阻塞了 UI 线程;
  • 原因 2:定时器周期过短(如 1ms),导致 UI 频繁刷新;
  • 解决方案:
    1. 耗时操作放入子线程,通过信号槽将进度值传递给主线程更新 ProgressBar(注意:Qt 禁止子线程直接操作 UI);
    2. 合理设置定时器周期(建议 50-200ms),平衡刷新频率和性能。
问题 2:进度文本显示异常(如位置偏移、颜色不对)

  • 原因 1:alignment属性设置不当;
  • 原因 2:未通过 QSS 自定义文本样式;
  • 解决方案:
    1. 设置alignmentQt::AlignCenter(默认居中,最稳妥);
    2. 通过 QSS 的QProgressBar::text选择器自定义文本颜色、字体大小。
问题 3:进度条反向增长不生效

  • 原因:invertAppearance属性仅控制进度增长方向,不改变文本方向;
  • 解决方案:若需要文本也反向显示,需同时设置textDirection属性为Qt::RightToLeft
问题 4:百分比计算错误(如最大值不是 100 时 % p 显示异常)

  • 原因:%p占位符会自动根据(value - minimum)/(maximum - minimum)计算百分比,与最大值是否为 100 无关;
  • 示例:若minimum=0maximum=200value=100,则%p显示 50%,无需手动计算。

二、CalendarWidget 控件:日期选择的标准化解决方案

QCalendarWidget 是 Qt 提供的日历控件,支持日期选择、月份 / 年份切换、日期范围限制等功能,无需手动绘制日历界面,可直接集成到项目中,大幅提升开发效率。无论是简单的日期选择框,还是复杂的日程管理界面,CalendarWidget 都能满足需求。

2.1 CalendarWidget 核心属性解析

CalendarWidget 的属性围绕日期展示和交互功能展开,以下是核心属性及实用场景:

属性名

功能说明

取值 / 类型

实用场景

selectedDate

当前选中的日期

QDate 类型

获取用户选择的日期

minimumDate

可选择的最小日期

QDate 类型

限制日期范围(如只能选择今天之后的日期)

maximumDate

可选择的最大日期

QDate 类型

限制日期范围(如只能选择近 30 天的日期)

firstDayOfWeek

每周第一天

Qt::Monday/Qt::Sunday 等

适配不同地区习惯(如国内周一为一周第一天)

gridVisible

是否显示表格边框

bool(默认 true)

简洁界面可隐藏边框

selectionMode

日期选择模式

QAbstractItemView::SingleSelection(默认,单选)等

仅支持单选日期(默认不支持多选)

navigationBarVisible

是否显示导航栏

bool(默认 true)

隐藏导航栏可固定显示某个月份

horizontalHeaderFormat

水平表头格式

QCalendarWidget::ShortDayNames(短名称,如 “一”)等

控制星期几的显示格式

verticalHeaderFormat

垂直表头格式

QCalendarWidget::NoVerticalHeader(隐藏)等

控制日期左侧的行号显示

dateEditEnabled

是否允许编辑日期

bool(默认 true)

禁止编辑可防止用户输入非法日期

2.2 核心信号解析

CalendarWidget 的信号主要用于响应日期选择和月份 / 年份切换,以下是最常用的信号:

信号名

触发时机

参数说明

实用场景

selectionChanged()

选中的日期发生改变时

无参数(通过 selectedDate () 获取日期)

实时获取用户选择的日期

activated(const QDate& date)

双击日期或按下回车键时

date:选中的日期

快速确认选择的日期

currentPageChanged(int year, int month)

切换月份 / 年份时

year:新年份;month:新月份

同步更新月份 / 年份显示标签

2.3 基础用法:快速实现日期选择功能

我们先在.ui文件中拖入“Calendar Widget”控件和一个label标签,用于显示选中的日期:

CalendarWidget 的基础用法只需几行代码,即可实现日期选择和展示。以下示例实现了 “选择日期后,在标签中显示选中日期” 的核心功能:

代码语言:javascript
复制
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

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

Widget::~Widget()
{
    delete ui;
}


void Widget::on_calendarWidget_selectionChanged()
{
    QDate date = ui->calendarWidget->selectedDate();
    qDebug() << date;

    ui->label->setText(date.toString());
}

运行程序后,选择日历中的任意日期,上方标签会实时显示 ,并且在控制台中也会打印出QDate对象的调试信息,能够直观展示日期选择和格式化功能。

2.2 CalendarWidget 常见问题与避坑指南

问题 1:无法选择指定日期范围外的日期,但用户仍可通过导航栏切换到该范围

  • 原因:minimumDatemaximumDate仅限制日期选择,不限制导航栏切换;
  • 解决方案:重写currentPageChanged信号,当切换到超出范围的月份时,自动切换回最近的合法月份:
代码语言:javascript
复制
connect(calendar, &QCalendarWidget::currentPageChanged, this, [=](int year, int month) {
    QDate currentMonthFirstDay(year, month, 1);
    QDate minDate = calendar->minimumDate();
    QDate maxDate = calendar->maximumDate();
    
    // 如果当前月份小于最小日期的月份,切换到最小日期的月份
    if (currentMonthFirstDay < minDate) {
        calendar->setCurrentPage(minDate.year(), minDate.month());
    }
    // 如果当前月份大于最大日期的月份,切换到最大日期的月份
    else if (currentMonthFirstDay > maxDate) {
        calendar->setCurrentPage(maxDate.year(), maxDate.month());
    }
});
问题 2:自定义样式不生效(如高亮今天、标记特殊日期)

  • 原因 1:QSS 选择器不正确(CalendarWidget 的子控件有固定的对象名,如qt_calendar_today);
  • 原因 2:重写paintCell时未先调用QCalendarWidget::paintCell,覆盖了默认样式;
  • 解决方案:
    1. 参考 Qt 官方文档,使用正确的 QSS 选择器;
    2. 重写paintCell时,先调用父类方法绘制默认样式,再绘制自定义内容。
问题 3:日期格式化显示异常(如星期显示为英文)

  • 原因:QDate::toString的格式符使用不当,默认根据系统 locale 显示;
  • 解决方案:使用中文格式符,或设置 locale 为中文:
代码语言:javascript
复制
// 方式1:使用中文格式符(dddd显示中文星期)
QString dateStr = selected.toString("yyyy年MM月dd日 dddd");

// 方式2:设置locale为中文
calendar->setLocale(QLocale::Chinese);

总结

显示类控件是 Qt 界面开发的重要组成部分,掌握 ProgressBar 和 CalendarWidget 的使用后,可进一步学习 Chart 控件(数据可视化)、OpenGL 控件(3D 图形显示)等高级显示控件,构建更专业、更具交互性的 Qt 应用。 如果本文对你有帮助,欢迎点赞、收藏、转发,如有疑问或建议,欢迎在评论区留言交流~ 后续将推出 Qt 控件系列其他文章,敬请期待!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、ProgressBar 控件:任务进度的可视化神器
    • 1.1 ProgressBar 核心属性解析
    • 1.2 基础用法:快速实现进度条展示
      • 1.2.1 静态进度展示(固定进度值)
      • 1.2.2 动态进度展示(结合定时器)
    • 1.3 样式自定义:打造个性化进度条
    • 1.4 ProgressBar 常见问题与避坑指南
      • 问题 1:进度条不更新或更新卡顿
      • 问题 2:进度文本显示异常(如位置偏移、颜色不对)
      • 问题 3:进度条反向增长不生效
      • 问题 4:百分比计算错误(如最大值不是 100 时 % p 显示异常)
  • 二、CalendarWidget 控件:日期选择的标准化解决方案
    • 2.1 CalendarWidget 核心属性解析
    • 2.2 核心信号解析
    • 2.3 基础用法:快速实现日期选择功能
    • 2.2 CalendarWidget 常见问题与避坑指南
      • 问题 1:无法选择指定日期范围外的日期,但用户仍可通过导航栏切换到该范围
      • 问题 2:自定义样式不生效(如高亮今天、标记特殊日期)
      • 问题 3:日期格式化显示异常(如星期显示为英文)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档