Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt:QWidget::paintEngine:不应再被调用_C++_Qt_Qpainter - Fatal编程技术网

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());
    //...
}