QCalendarWidget需连接selectionChanged信号才能获取选中日期;用setMinimumDate/setMaximumDate限制范围,细粒度禁用需重写paintCell和mousePressEvent;setSelectedDate后须调用setCurrentPage定位月份;高DPI下模糊应启用AA_EnableHighDpiScaling或换QTableView实现。

QCalendarWidget 选中日期后怎么获取值
默认点击日期不会触发信号,必须手动连接 selectionChanged() 信号——很多人卡在这步,以为点完就能直接读 selectedDate(),结果拿到的是初始化日期。
正确做法是:
- 用
connect(calendar, &QCalendarWidget::selectionChanged, this, &MyClass::onDateSelected)绑定信号 - 槽函数里调用
calendar->selectedDate()获取QDate对象 - 注意:首次构造后
selectedDate()返回的是当前系统日期,不是控件显示的月份首日
怎么限制可选日期范围(比如只允许选未来7天)
QCalendarWidget 没有内置的「禁用日期」功能,靠 setMinimumDate() 和 setMaximumDate() 只能锁死整个时间区间,不能做条件性禁用(如周末不可选、节假日灰掉)。
真要实现细粒度控制,必须重写 paintCell() 并配合 isCellPainted() 逻辑:
- 继承
QCalendarWidget,重载paintCell() - 在函数里用
date.isValid()判断是否在允许范围内,再决定是否调用父类绘制 - 同时覆盖
mousePressEvent(),对非法日期直接return,避免点击生效 - 注意:
paintCell()里不能调用update()或触发重绘,否则会递归崩溃
为什么设置日期后控件不跳转到对应月份
调用 setSelectedDate() 或 setCurrentPage() 不会自动滚动到可视区域——这是 Qt 的设计选择,不是 bug。
想让日历“定位”到某天,必须两步走:
- 先调用
setSelectedDate(date) - 再调用
showToday()或setCurrentPage(date.year(), date.month()) - 如果用
showToday(),它会跳转到今天所在月,不是目标日期所在月,容易误用 - 推荐组合:
calendar->setSelectedDate(targetDate); calendar->setCurrentPage(targetDate.year(), targetDate.month());
QCalendarWidget 在高 DPI 缩放下文字模糊或错位
Qt 5.14+ 默认启用高 DPI 支持,但 QCalendarWidget 的单元格绘制没完全适配缩放因子,尤其 Windows 上字体发虚、格线偏移。
临时缓解方案:
- 启动时加环境变量:
QT_SCALE_FACTOR=1(粗暴但有效) - 更稳妥的做法:在 main 函数开头调用
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling),并确保QApplication构造早于任何控件创建 - 自定义样式表无法修复绘制级问题,
font-size调整只会让模糊更明显
真正可靠的解法是弃用 QCalendarWidget,改用 QTableView + 自定义模型实现日历——但这意味着你要自己处理周起始、月切换、日期格式化等所有逻辑。


















