0
votes

I want to create calendar, that will mark several dates entered by user. So I have subclassed QCalendarWidget and reimplemented painCell function. Here is my simplified code:

MyCalendar::MyCalendar(QWidget *parent)
    : QCalendarWidget(parent)
{   
    painter = new QPainter(this);   
}
void MyCalendar::setHolidays(QDate date)
{
    paintCell(painter, rect(),date);        
}

void MyCalendar::paintCell(QPainter * painter, const QRect & rect, const QDate & date) const
{
    painter->setBrush(Qt::red);
    QCalendarWidget::paintCell(painter, rect, date);
}

I can't do it though, because when creating QPainter object i am getting this message: "QWidget::paintEngine: Should no longer be called QPainter::begin: Paint device returned engine == 0, type: 1"

When I am not setting painter parent, I get this error when trying to set brush: "QPainter::setBrush: Painter not active" I think, I am creating QPainter object in a wrong place. Anyone knows, how to resolve this?

I was using Qt wiki snippet: https://wiki.qt.io/How_to_create_a_custom_calender_widget

1
painter.setBrush(Qt::red); or painter->setBrush(Qt::red);? - eyllanesc
Right, painter->setBrush(Qt::red). But this is not the problem, I made this mistake when editing my code here, on stack page - karollo
I believe, calling paintCell() in setHolidays() might be the wrong way. Instead, IMHO setHolydays() should call updateCells() (or updateCell() for a specific date). The paintCell() is a virtual method which is called out of the paint() method (inherited from QWidget). It should check for a special day to modify appearance. It probably gets a QPainter instance as argument which is managed inside QCalendarWidget - no need to create your own. I just see the answer of eyllanesc. It seems he had the same idea... - Scheff's Cat
As you mentioned the MCVE on the Qt Wiki, there is also a bigger Calendar Widget Example in Qt doc. which I find worth to be mentioned. - Scheff's Cat

1 Answers

2
votes

You should not draw directly since the paintCell method is called internally, it is appropriate to save the dates in a list, and if the date used by paintCell is contained in that list, draw it in a personalized way:

#ifndef MYCALENDAR_H
#define MYCALENDAR_H

#include <QCalendarWidget>
#include <QPainter>
class MyCalendar : public QCalendarWidget
{
public:
    MyCalendar(QWidget *parent=Q_NULLPTR):QCalendarWidget{parent}{

    }
    void addHoliday(const QDate &date){
        mDates<<date;
        updateCell(date);
    }
    void paintCell(QPainter * painter, const QRect & rect, const QDate & date) const{
        if(mDates.contains(date)){
            painter->save();
            painter->setBrush(Qt::red);
            painter->drawRect(rect);
            painter->drawText(rect, Qt::AlignCenter|Qt::TextSingleLine, QString::number(date.day()));
            painter->restore();
        }
        else
            QCalendarWidget::paintCell(painter, rect, date);

    }
private:
    QList<QDate> mDates;
};

#endif // MYCALENDAR_H