0

I try to make a corner in the cells of my QCalendarWidget. So I made a QItemDelegate in which I draw my triangle.
As the screenshot shows, the delegate works fine on the first column, but is completely broken on the others.
I don't understand where this comes from (I'm new to Qt, so maybe I did something wrong).
Here is the code:

# ---------------------------------
# ------ CalendarDayDelegate ------
class CalendarDayDelegate(QItemDelegate):
    def __init__(self, parent=None, projects=None):
        super(CalendarDayDelegate, self).__init__(parent=parent)
        self.projects = projects

    def paint(self, painter, option, index):
        painter._date_flag = index.row() > 0
        super(CalendarDayDelegate, self).paint(painter, option, index)

        if painter._date_flag:
            rect = option.rect
            corner = QPolygon([
                rect.topRight(),
                QPoint(rect.center().x() + (rect.center().x() / 2), rect.top()),
                QPoint(rect.bottomRight().x(), rect.center().y())
            ])

            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 painter._date_flag:
            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._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)

And the screenshot
screenshot of QCalendarWidget

musicamante
  • 41,230
  • 6
  • 33
  • 58
Pixidream
  • 13
  • 3

1 Answers1

0

The issue is with the second point of the polygon: since you're setting it based on the x of the center, every new column of the table will have a different coordinate reference.

If you just print the rect, you'll see the result:

    def paint(self, painter, option, index):
        # ...
        if index.row() == 1:
            print(index.column(), rect.center())

Which will output:

>>> 0 PyQt5.QtCore.QPoint(15, 41)
>>> 1 PyQt5.QtCore.QPoint(46, 41)
>>> 2 PyQt5.QtCore.QPoint(77, 41)
>>> 3 PyQt5.QtCore.QPoint(108, 41)
>>> 4 PyQt5.QtCore.QPoint(139, 41)

Since you're adding half of the "center x" coordinate everytime, the result is that the second point gets far and far away everytime you get a new rectangle based on a non-zero column.

If you want that corner to start at 75% of the rect width, just use a the top right corner as a reference, and then subtract/add relative coordinates (QPoint) from/to it:

        ref = rect.topRight()
        corner = QPolygon([
            ref, 
            ref + QPoint(-rect.width() / 4, 0), 
            ref + QPoint(0, rect.height() / 2)
        ])
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • Thanks a lot ! I didn't understand that `rect.center.x()` was absolute. The doc is not very explicit about this, or I'm not looking for it right, which is possible ... in any case, thank you very much for the help! – Pixidream Jun 23 '21 at 08:38
  • @Pixidream Qt uses the same concepts of Analytic Geometry as basis for its coordinate system, so coordinates are always absolute: besides, since topRight is absolute, why should center be relative? – musicamante Jun 23 '21 at 14:55