
目录
[一、ProgressBar 控件:任务进度的可视化神器](#一、ProgressBar 控件:任务进度的可视化神器)
[1.1 ProgressBar 核心属性解析](#1.1 ProgressBar 核心属性解析)
[1.2 基础用法:快速实现进度条展示](#1.2 基础用法:快速实现进度条展示)
[1.2.1 静态进度展示(固定进度值)](#1.2.1 静态进度展示(固定进度值))
[1.2.2 动态进度展示(结合定时器)](#1.2.2 动态进度展示(结合定时器))
[1.3 样式自定义:打造个性化进度条](#1.3 样式自定义:打造个性化进度条)
[1.4 ProgressBar 常见问题与避坑指南](#1.4 ProgressBar 常见问题与避坑指南)
[问题 1:进度条不更新或更新卡顿](#问题 1:进度条不更新或更新卡顿)
[问题 2:进度文本显示异常(如位置偏移、颜色不对)](#问题 2:进度文本显示异常(如位置偏移、颜色不对))
[问题 3:进度条反向增长不生效](#问题 3:进度条反向增长不生效)
[问题 4:百分比计算错误(如最大值不是 100 时 % p 显示异常)](#问题 4:百分比计算错误(如最大值不是 100 时 % p 显示异常))
[二、CalendarWidget 控件:日期选择的标准化解决方案](#二、CalendarWidget 控件:日期选择的标准化解决方案)
[2.1 CalendarWidget 核心属性解析](#2.1 CalendarWidget 核心属性解析)
[2.2 核心信号解析](#2.2 核心信号解析)
[2.3 基础用法:快速实现日期选择功能](#2.3 基础用法:快速实现日期选择功能)
[2.2 CalendarWidget 常见问题与避坑指南](#2.2 CalendarWidget 常见问题与避坑指南)
[问题 1:无法选择指定日期范围外的日期,但用户仍可通过导航栏切换到该范围](#问题 1:无法选择指定日期范围外的日期,但用户仍可通过导航栏切换到该范围)
[问题 2:自定义样式不生效(如高亮今天、标记特殊日期)](#问题 2:自定义样式不生效(如高亮今天、标记特殊日期))
[问题 3:日期格式化显示异常(如星期显示为英文)](#问题 3:日期格式化显示异常(如星期显示为英文))
前言
在 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 的基础用法非常简洁,通过设置minimum、maximum和value三个核心属性,即可实现进度展示。以下是两种常见的基础场景示例:
1.2.1 静态进度展示(固定进度值)
适用于展示已知进度的场景(如操作完成度提示):
cpp
#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控件:


编辑代码:
cpp
#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 频繁刷新;
- 解决方案:
- 耗时操作放入子线程,通过信号槽将进度值传递给主线程更新 ProgressBar(注意:Qt 禁止子线程直接操作 UI);
- 合理设置定时器周期(建议 50-200ms),平衡刷新频率和性能。
问题 2:进度文本显示异常(如位置偏移、颜色不对)
- 原因 1:
alignment属性设置不当;- 原因 2:未通过 QSS 自定义文本样式;
- 解决方案:
- 设置
alignment为Qt::AlignCenter(默认居中,最稳妥);- 通过 QSS 的
QProgressBar::text选择器自定义文本颜色、字体大小。
问题 3:进度条反向增长不生效
- 原因:
invertAppearance属性仅控制进度增长方向,不改变文本方向;- 解决方案:若需要文本也反向显示,需同时设置
textDirection属性为Qt::RightToLeft。
问题 4:百分比计算错误(如最大值不是 100 时 % p 显示异常)
- 原因:
%p占位符会自动根据(value - minimum)/(maximum - minimum)计算百分比,与最大值是否为 100 无关;- 示例:若
minimum=0、maximum=200、value=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 的基础用法只需几行代码,即可实现日期选择和展示。以下示例实现了 "选择日期后,在标签中显示选中日期" 的核心功能:
cpp
#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:无法选择指定日期范围外的日期,但用户仍可通过导航栏切换到该范围
- 原因:
minimumDate和maximumDate仅限制日期选择,不限制导航栏切换;- 解决方案:重写
currentPageChanged信号,当切换到超出范围的月份时,自动切换回最近的合法月份:
cpp
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,覆盖了默认样式;- 解决方案:
- 参考 Qt 官方文档,使用正确的 QSS 选择器;
- 重写
paintCell时,先调用父类方法绘制默认样式,再绘制自定义内容。
问题 3:日期格式化显示异常(如星期显示为英文)
- 原因:
QDate::toString的格式符使用不当,默认根据系统 locale 显示;- 解决方案:使用中文格式符,或设置 locale 为中文:
cpp
// 方式1:使用中文格式符(dddd显示中文星期)
QString dateStr = selected.toString("yyyy年MM月dd日 dddd");
// 方式2:设置locale为中文
calendar->setLocale(QLocale::Chinese);
总结
显示类控件是 Qt 界面开发的重要组成部分,掌握 ProgressBar 和 CalendarWidget 的使用后,可进一步学习 Chart 控件(数据可视化)、OpenGL 控件(3D 图形显示)等高级显示控件,构建更专业、更具交互性的 Qt 应用。
如果本文对你有帮助,欢迎点赞、收藏、转发,如有疑问或建议,欢迎在评论区留言交流~ 后续将推出 Qt 控件系列其他文章,敬请期待!