I am trying to override QCalendarWidget's paintCell() method to paint a red outline on today's date cell and draw events that will be defined by the user. For my calendar, I used a QItemDelegate to change the alignment of the date flags so I would have more room to draw events. However, I can't seem to get both the QItemDelegate and paintCell() working together. I can only have one or the other work at one time. If I try to do both, only the Delegate shows and nothing is painted.
from PySide2.QtWidgets import QMainWindow, QCalendarWidget, QApplication, QItemDelegate, QTableView
from PySide2.QtGui import QPen
from PySide2.QtCore import Qt
import sys
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()
self.calendar = CustomCalendar()
self.calendarview = self.calendar.findChild(QTableView, "qt_calendar_calendarview")
self.calendardelegate = CalendarItemDelegate(self.calendarview)
self.calendarview.setItemDelegate(self.calendardelegate)
self.setCentralWidget(self.calendar)
self.show()
class CustomCalendar(QCalendarWidget):
def __init__(self, parent=None):
super().__init__()
def paintCell(self, painter, rect, date):
QCalendarWidget.paintCell(self, painter, rect, date)
pen = QPen()
pen.setColor(Qt.red)
painter.setPen(pen)
if date == date.currentDate():
painter.save()
painter.drawRect(rect.adjusted(0, 0, -1, -1))
painter.restore()
class CalendarItemDelegate(QItemDelegate):
def paint(self, painter, option, index):
painter._date_flag = index.row() > 0
super().paint(painter, option, index)
def drawDisplay(self, painter, option, rect, text):
if painter._date_flag:
option.displayAlignment = Qt.AlignTop | Qt.AlignLeft
super().drawDisplay(painter, option, rect, text)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
How can I get both to work at once?
Delegate
PaintCell


When a custom item delegate is set on the calendar widget, the default
paintCellis just ignored, as it's responsibility of the (private) delegate to call it.Since you're using a QItemDelegate, you can take advantage of the
drawFocus()function and check if theoption.statehas theState_Selectedflag set (technically, you could do it in thedrawDisplay()too, since the function is called anyway and the option has the same values):