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

QCalendarWidget中QItemDelegate跨列渲染效果不一致问题求助

问题根源

你自定义委托绘制异常的核心原因是三角形顶点坐标计算逻辑错误:
option.rect保存的是单元格在日历表格视图中的全局位置,而非单元格内部的相对坐标,你直接使用全局的center.x()计算顶点,第一列单元格x轴偏移量小,计算结果刚好落在单元格范围内;越靠右的列x轴偏移量越大,计算出的顶点会直接溢出单元格,因此显示异常。

修复后的代码

仅需修改CalendarDayDelegate的坐标计算逻辑即可:

# ---------------------------------
# ------ CalendarDayDelegate ------
class CalendarDayDelegate(QItemDelegate):
    def __init__(self, parent=None, projects=None):
        super(CalendarDayDelegate, self).__init__(parent=parent)
        self.projects = projects
        # 可自定义角标大小,也可以用rect.width()*0.2这类比例实现自适应
        self.corner_size = 15

    def paint(self, painter, option, index):
        painter._date_flag = index.row() > 0
        super(CalendarDayDelegate, self).paint(painter, option, index)
        if not painter._date_flag:
            return
        
        rect = option.rect
        # 基于单元格边界计算右上角三角形坐标,适配所有列
        corner = QPolygon([
            rect.topRight(),
            QPoint(rect.right() - self.corner_size, rect.top()),
            QPoint(rect.right(), rect.top() + self.corner_size)
        ])

        painter.save()
        painter.setRenderHint(painter.Antialiasing)
        painter.setBrush(QBrush(QColor(Qt.darkGreen)))
        painter.setPen(QPen(QColor(Qt.darkGreen)))
        painter.drawPolygon(corner)
        painter.restore()

    def drawDisplay(self, painter, option, rect, text):
        if getattr(painter, '_date_flag', False):
            option.displayAlignment = Qt.AlignTop | Qt.AlignLeft
        super(CalendarDayDelegate, self).drawDisplay(painter, option, rect, text)

# ----------------------
# ------ Calendar ------
class MonthReviewCalendar(QCalendarWidget):
    def __init__(self, parent=None):
        super(MonthReviewCalendar, self).__init__(parent=parent)
        # 补充你自己的项目数据初始化逻辑即可
        self._raw_projects = []
        self._init_calendar()

    def _init_calendar(self):
        self.setVerticalHeaderFormat(
            self.verticalHeaderFormat().NoVerticalHeader
        )
        self.setFirstDayOfWeek(Qt.Monday)

        self.calendar_view = self.findChild(
            QTableView, "qt_calendar_calendarview"
        )
        self.calendar_delegate = CalendarDayDelegate(
            projects=self._raw_projects
        )
        self.calendar_view.setItemDelegate(self.calendar_delegate)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 20:06:08