C++ Qt:QWidget::paintEngine:不应再被调用
我正在尝试制作一个应用程序,你可以用手指在画布上画画。C++ Qt:QWidget::paintEngine:不应再被调用,c++,qt,qpainter,C++,Qt,Qpainter,我正在尝试制作一个应用程序,你可以用手指在画布上画画。 为了实现这一点,我将QWidget子类化为MFCanvas,并在QML中将该类注册为 qmlRegisterType(),实现虚拟的paintEvent()功能,和 使用paintEvent()内的QPainter在其上绘制功能。 问题: 施工时,QPainter抛出此警告: QWidget::paintEngine:不应再被调用 然后,会抛出几个其他相关警告: QPainter::begin: Paint device returned
为了实现这一点,我将
QWidget
子类化为MFCanvas
,并在QML中将该类注册为qmlRegisterType()
,实现虚拟的paintEvent()代码>功能,和
使用paintEvent()内的QPainter
在其上绘制代码>功能。
问题:
施工时,QPainter
抛出此警告:
QWidget::paintEngine:不应再被调用
然后,会抛出几个其他相关警告:
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
难怪,QPainter
没有画任何东西……
另外,我是否应该调用paintEvent()代码>我自己?
还是应该由QWidget
调用每一帧,而我不知怎么搞砸了它?
我在网上搜索了一下,但我找到的所有帖子要么没有答案,要么都在哪里找到了
使用非QWidget
我的代码:
mfcanvas.cpp:
#include "mfcanvas.h"
#include <QDebug>
#include <QPainter>
#include <QVector2D>
#include <QList>
MFCanvas::MFCanvas(QWidget *parent) : QWidget(parent)
{
paths = new QList<QList<QVector2D>*>();
current = NULL;
QWidget::resize(100, 100);
}
MFCanvas::~MFCanvas()
{
delete paths;
}
void MFCanvas::paintEvent(QPaintEvent *)
{
if(current!=NULL){
if(current->length() > 1){
QPainter painter(this);
painter.setPen(Qt::black);
for(int i = 1; i < current->length(); i++){
painter.drawLine(current->at(i-1).x(), current->at(i-1).y(), current->at(i).x(), current->at(i).y());
}
}
}
}
void MFCanvas::pressed(float x, float y)
{
if(current==NULL){
qDebug() << "null:"<<current;
current = new QList<QVector2D>();
current->append(QVector2D(x, y));
}else{
qDebug() << "current:"<<current;
}
paintEvent(NULL);
}
void MFCanvas::update(float x, float y)
{
current->append(QVector2D(x, y));
}
void MFCanvas::resize(int w, int h)
{
QWidget::resize(w, h);
}
void MFCanvas::paint(QPainter *painter)
{
painter->translate(-translation.x(), -translation.y());
//...
}
如果您需要任何其他信息,请告诉我。
提前谢谢你!=)
在mfcanvas.cpp中,void mfcanvas::pressed(float x,float y)
函数,行
paintEvent(NULL);
这似乎令人不安。在类似的代码中尝试过-我得到了相同的错误
建议的解决方案:使用this->repaint()
或this->update()
而不是paintEvent(NULL)
重新绘制小部件似乎更合适
可能的解释:看起来不应该这么简单地调用paintEvent()(就像调用paint()函数时调用paintEvent()。据我从QPainter文档了解,QPainter与QPaintDevice和QPaintEngine一起工作,这三者构成了绘画的基础。错误QWidget::paintEngine:不应该再被调用了
,这让它变得非常直白。台词
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
可能表示此画家的QPaintDevice没有提供QPaintEngine(如QPaintDevice::paintEngine
)。我们可以假设此QPaintEngine是由绘制设备本身生成或以其他方式调用的,例如,当在小部件上调用paint()函数时。我自己也找到了一个简单的解决方案:
不是从QWidget派生,而是从QQuickPaintedItem派生。QQuickPaintedItem是一个类,它完全是为了满足我的需要而创建的:使用QPainter在QML元素上绘制。以下是代码(缩小到基本部分):
mfcanvas.h:
class MFCanvas : public QQuickPaintedItem
{
Q_OBJECT
public:
explicit MFCanvas(QQuickItem *parent = 0);
~MFCanvas();
protected:
void paint(QPainter *painter);
mfcanvas.cpp:
#include "mfcanvas.h"
#include <QDebug>
#include <QPainter>
#include <QVector2D>
#include <QList>
MFCanvas::MFCanvas(QWidget *parent) : QWidget(parent)
{
paths = new QList<QList<QVector2D>*>();
current = NULL;
QWidget::resize(100, 100);
}
MFCanvas::~MFCanvas()
{
delete paths;
}
void MFCanvas::paintEvent(QPaintEvent *)
{
if(current!=NULL){
if(current->length() > 1){
QPainter painter(this);
painter.setPen(Qt::black);
for(int i = 1; i < current->length(); i++){
painter.drawLine(current->at(i-1).x(), current->at(i-1).y(), current->at(i).x(), current->at(i).y());
}
}
}
}
void MFCanvas::pressed(float x, float y)
{
if(current==NULL){
qDebug() << "null:"<<current;
current = new QList<QVector2D>();
current->append(QVector2D(x, y));
}else{
qDebug() << "current:"<<current;
}
paintEvent(NULL);
}
void MFCanvas::update(float x, float y)
{
current->append(QVector2D(x, y));
}
void MFCanvas::resize(int w, int h)
{
QWidget::resize(w, h);
}
void MFCanvas::paint(QPainter *painter)
{
painter->translate(-translation.x(), -translation.y());
//...
}
如您所见,提供了一个简单的paint()函数,它将指针交给QPainter,即可使用。=) 这里很好地解释了这一点:
简而言之:不要试图直接从输入事件处理程序绘制,
但是在小部件中重载paintEvent方法并创建
油漆工在那里。仅使用输入事件修改内部事件
数据模型,并在paintEvent中使用QPaint将其显示在输出路径上
void MFCanvas::paint(QPainter *painter)
{
painter->translate(-translation.x(), -translation.y());
//...
}