子类化QCalendarWidget时paintCell()函数的Painter错误求助
解决QCalendarWidget自定义绘制的Painter错误问题
你的问题核心是对Qt的绘制机制理解有偏差,QPainter的创建和使用必须遵循Qt的绘制生命周期,不能随意在构造函数里创建,也不能直接手动调用paintCell。下面一步步帮你修正:
错误原因拆解
- 构造函数里创建
QPainter并绑定到this:此时Widget还未进入绘制流程,没有可用的paint engine,所以触发Paint device returned engine == 0错误。 - 手动调用
paintCell(painter, rect(),date):paintCell是Qt框架在绘制日历单元格时自动调用的方法,你直接调用时,要么Painter未激活,要么绘制上下文不正确。 - 没有存储需要标记的日期集合:你的
setHolidays只能传单个日期,还没法支持多个日期标记。
修正后的代码实现
首先调整类的定义,添加一个存储标记日期的集合,移除不必要的painter成员:
// MyCalendar.h #include <QCalendarWidget> #include <QSet> #include <QDate> class MyCalendar : public QCalendarWidget { Q_OBJECT public: explicit MyCalendar(QWidget *parent = nullptr); // 修改为支持添加多个日期的方法 void addHoliday(const QDate& date); void clearHolidays(); protected: void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const override; private: QSet<QDate> m_holidays; // 存储需要标记的日期 };
然后实现cpp文件:
// MyCalendar.cpp #include "MyCalendar.h" #include <QPainter> MyCalendar::MyCalendar(QWidget *parent) : QCalendarWidget(parent) { // 这里不需要创建QPainter! } void MyCalendar::addHoliday(const QDate& date) { m_holidays.insert(date); update(); // 触发重绘,让框架重新调用paintCell更新所有单元格 } void MyCalendar::clearHolidays() { m_holidays.clear(); update(); } void MyCalendar::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const { // 先判断当前日期是否需要标记 if (m_holidays.contains(date)) { painter->setBrush(Qt::red); // 先绘制背景(可选,也可以先调用父类再叠加) painter->drawRect(rect); } // 调用父类的paintCell绘制默认的日历内容(日期文字等) QCalendarWidget::paintCell(painter, rect, date); }
关键修正点说明
- 移除成员QPainter:
paintCell参数里的painter是Qt框架已经激活好的,直接用就行,不需要自己创建。框架会在绘制每个单元格时自动传入正确的Painter对象,确保绘制上下文有效。 - 用集合存储标记日期:
QSet<QDate>可以高效判断某个日期是否需要标记,支持添加多个日期。 - 通过update()触发重绘:当你添加/移除标记日期后,调用
update()让Qt重新绘制日历,这样paintCell会被自动调用,更新所有单元格的显示。 - 绘制顺序:先绘制自定义的标记(比如红色背景),再调用父类方法绘制默认内容,这样日期文字会显示在红色背景上;如果想让标记叠加在默认内容上,可以调换顺序。
使用示例
在你的主代码里,这样调用:
MyCalendar* calendar = new MyCalendar(this); calendar->addHoliday(QDate(2024, 10, 1)); calendar->addHoliday(QDate(2024, 12, 25));
这样这两个日期就会被标记成红色背景啦。
内容的提问来源于stack exchange,提问作者karollo
相关产品推荐
相关产品推荐

