You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QCalendarWidget如何设置多选模式?支持Ctrl多选并返回日期列表

QCalendarWidget 实现多选模式(支持Ctrl键多选)

QCalendarWidget 默认仅提供 NoSelection 和 SingleSelection 两种选择模式,没有原生的多选支持,但可以通过自定义子类实现按住Ctrl键多选日期的功能,核心思路是通过事件监听维护选中日期集合,并自定义绘制选中状态。

实现核心步骤

  • 自定义子类继承 QCalendarWidget,用QSet<QDate>(Python中用set)存储选中的日期
  • 重写mousePressEvent:根据Ctrl键状态处理选中逻辑——Ctrl+点击切换当前日期的选中状态,无Ctrl则清空原有选中项并选中当前日期
  • 重写paintCell:对选中日期进行特殊绘制,提供直观的视觉反馈
  • 添加公共方法返回排序后的选中日期列表

代码示例(PyQt5)

from PyQt5.QtWidgets import QCalendarWidget, QApplication, QStyle
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtCore import QDate, Qt
import sys

class MultiSelectCalendar(QCalendarWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.selected_dates = set()

    def mousePressEvent(self, event):
        date = self.dateAt(event.pos())
        if not date.isValid():
            super().mousePressEvent(event)
            return

        modifiers = QApplication.keyboardModifiers()
        if modifiers == Qt.ControlModifier:
            # Ctrl按下:切换当前日期的选中状态
            if date in self.selected_dates:
                self.selected_dates.remove(date)
            else:
                self.selected_dates.add(date)
        else:
            # 无Ctrl:清空原有选中项,仅选中当前日期
            self.selected_dates.clear()
            self.selected_dates.add(date)
        self.updateCell(date)
        super().mousePressEvent(event)

    def paintCell(self, painter, rect, date):
        super().paintCell(painter, rect, date)
        # 绘制选中日期的高亮背景
        if date in self.selected_dates:
            painter.save()
            highlight_color = self.palette().highlight().color()
            painter.fillRect(rect, highlight_color)
            # 绘制白色日期文字,保证可读性
            text = str(date.day())
            painter.setPen(self.palette().highlightedText().color())
            painter.drawText(rect, Qt.AlignCenter, text)
            painter.restore()

    def get_selected_dates(self):
        # 返回排序后的选中日期列表
        return sorted(self.selected_dates)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    cal = MultiSelectCalendar()
    cal.show()
    
    # 示例:点击日历后打印选中日期
    def print_selected():
        dates = [d.toString(Qt.ISODate) for d in cal.get_selected_dates()]
        print(f"选中日期:{dates}")
    
    cal.clicked.connect(print_selected)
    sys.exit(app.exec_())

关键细节说明

  • 用集合存储选中日期,避免重复选中同一日期
  • 重绘逻辑使用系统默认高亮配色,也可替换为自定义颜色(如QColor("#2196F3"))
  • get_selected_dates返回排序后的列表,方便后续业务处理
  • 完全贴合原生日历的交互逻辑,用户学习成本低

内容的提问来源于stack exchange,提问作者leo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:40:31