QWidget::paintEngine: Should no longer be called错误情况总结
目录
1. Qt绘图报错描述
2. 错误原因及解决方法
2.1.第1种情况
2.2. 第2种情况
3. 总结
1. Qt绘图报错描述
当用QPainter绘图时,如果使用不当,Qt会报如下错误提示:

2. 错误原因及解决方法
2.1.第1种情况
绘图代码不在QWidget::paintEvent重载函数内或不在被QWidget::paintEvent函数调用的函数内。Qt规定:任何窗体内的绘图必须放在QWidget::paintEvent重载函数内或被QWidget::paintEvent函数调用的函数内。如下代码:
#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);m_pImage = new QImage("b.png");auto b = m_pImage->isNull();Q_ASSERT(!b);QPainter p(this);p.drawImage(rect(), *m_pImage, m_pImage->rect());
}
原意是想把成员变量m_pImage表示的图像在Widget类的构造函数中绘制到Widget窗体类的矩形内,但报1节描述的错误。正确的做法是应把绘图代码移动到paintEvent重载函数内,即如下那样:
#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);m_pImage = new QImage("b.png");auto b = m_pImage->isNull();Q_ASSERT(!b);
}Widget::~Widget()
{delete ui;
}void Widget::paintEvent(QPaintEvent *event)
{QPainter p(this);p.drawImage(rect(), *m_pImage, m_pImage->rect());
}
Widget.h文件如下:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:virtual void paintEvent(QPaintEvent *event) override;
private:Ui::Widget *ui;QImage* m_pImage;
};
#endif // WIDGET_H
2.2. 第2种情况
图像绘制到窗体中的小部件上,如:绘制图像到Widget窗体中的某个QLabel上,像如下代码那样:
#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);m_pImage = new QImage("b.png");auto b = m_pImage->isNull();Q_ASSERT(!b);
}Widget::~Widget()
{delete ui;
}void Widget::paintEvent(QPaintEvent *event)
{QPainter p(ui->label);p.drawImage(ui->label->rect(), *m_pImage, m_pImage->rect());
}
其中ui->label为Widget窗体上的一个QLabel,同样报1节的错误。Qt规定:任何窗体子部件的绘图必须放在该子部件的paintEvent重载函数内或在被子部件的paintEvent函数调用的函数内。解决方法如下:
1):自定义子部件类。
2):在自定义部件类的paintEvent重载函数内绘图。
如下代码就是自定义了一个名为CMyLabel的类,在该类的paintEvent重载函数内绘图成功:
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>class CMyLabel : public QLabel
{Q_OBJECTpublic:explicit CMyLabel(QWidget *parent = nullptr);~CMyLabel();private:virtual void paintEvent(QPaintEvent *event) override;private:QImage* m_pImage;
};#endif // MYLABEL_H
#include "myLabel.h"
#include "ui_myLabel.h"
#include<QPainter>
#include<QPaintEvent>
CMyLabel::CMyLabel(QWidget *parent) :QLabel(parent)
{m_pImage = new QImage("d:/b.png");auto b = m_pImage->isNull();Q_ASSERT(!b);
}CMyLabel::~CMyLabel()
{}
void CMyLabel::paintEvent(QPaintEvent *event)
{QPainter p(this);p.drawImage(rect(), *m_pImage, m_pImage->rect());
}

3. 总结
为了保证Qt绘图时不报错,能成功,必须遵循如下规定:
1):任何窗体内的绘图必须放在QWidget::paintEvent重载函数内或被QWidget::paintEvent函数调用
的函数内。
2):任何窗体子部件的绘图必须放在该子部件的paintEvent重载函数内或在被子部件的paintEvent函
数调用的函数内。
