【问题标题】:Qt: QWidget::paintEngine: Should no longer be calledQt:QWidget::paintEngine:不应再被调用
【发布时间】:2014-09-11 07:15:51
【问题描述】:

我正在尝试制作一个应用程序,您可以在其中用手指在画布上绘图。
为了实现这一点,我将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);
}

main.cpp:

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QSurfaceFormat>
#include "creator.h"
#include "mfcanvas.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    qmlRegisterType<MFCanvas>("com.cpp.mfcanvas", 1, 0, "MFCanvas");

    QQmlApplicationEngine engine;

    QQmlComponent *component = new QQmlComponent(&engine);
    QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));

    Creator creator(component);
    QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)), &creator, SLOT(create(QQmlComponent::Status)));

    component->loadUrl(QUrl("qrc:///main.qml"));

    int rv;

    rv = app.exec();
    delete component;
    return rv;
}

creator.cpp:

#include "creator.h"
#include <QQuickWindow>
#include <QDebug>

Creator::Creator(QQmlComponent *component)
{
    this->component = component;
}

void Creator::create(QQmlComponent::Status status)
{
    if(status == QQmlComponent::Ready){
        QObject *topLevel = component->create();
        QQuickWindow::setDefaultAlphaBuffer(true);
        QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

        QSurfaceFormat surfaceFormat = window->requestedFormat();
        window->setFormat(surfaceFormat);
        window->show();
    }
}

main.qml:(重要部分)

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import com.cpp.mfcanvas 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("MFCanvas")

    onSceneGraphInitialized: {
        drawMenu.visible = true;
        lineWidth.visible = true;
        colorMenu.visible = true;
        drawMenu.visible = false;
        lineWidth.visible = false;
        colorMenu.visible = false;
    }

    Rectangle {
        id: main
        anchors.fill: parent

        property real toolsH: 15
        property real iconW: 25

        property real menuH: 8
        property real menuW: 16

        property real dpi: (Screen.logicalPixelDensity == undefined ? 6 : Screen.logicalPixelDensity) * 1.5

        property color choosenColor: Qt.hsla(hue.value, saturation.value, luminance.value, 1)

        Text {
            anchors.centerIn: parent
            font.pointSize: 60
            text: "MFCanvas"
        }

        MFCanvas {
            id: canvas
            Component.onCompleted: {
                canvas.resize(main.width, main.height);
            }
        }
    //...
    }
}

如果您需要任何其他信息,请告诉我。
先感谢您! =)

【问题讨论】:

    标签: c++ qt qpainter


    【解决方案1】:

    这里解释得很好:

    https://forum.qt.io/topic/64693

    简而言之:不要尝试直接从输入事件处理程序中进行绘制, 但在您的小部件中重载paintEvent方法并创建 QPainter 那里。独占使用输入事件修改内部 数据模型并在paintEvent中使用QPainter将其显示在输出路径上。

    【讨论】:

      【解决方案2】:

      在您的 mfcanvas.cpp, void MFCanvas::pressed(float x, float y) 函数中,行

      paintEvent(NULL);
      

      似乎令人不安。用类似的代码尝试过 - 我得到了同样的错误。

      建议的解决方案:使用this-&gt;repaint()this-&gt;update() 而不是paintEvent(NULL) 重新绘制小部件似乎更合适。

      可能的解释: 看起来像 paintEvent() 不应该这么简单地调用(就像 paintEvent() 时调用paint() 函数被调用)。据我从 QPainter 文档中了解到,QPainter 与 QPaintDevice 和 QPaintEngine 一起工作,这三者构成了绘画的基础。错误QWidget::paintEngine: Should no longer be called 直截了当。线条

      QPainter::begin: Paint device returned engine == 0, type: 1 
      QPainter::setPen: Painter not active
      

      可能表明此画家的 QPaintDevice 没有提供 QPaintEngine(如 QPaintDevice::paintEngine)。可以假设这个 QPaintEngine 是由绘图设备本身生成或以其他方式调用存在的,例如,当在小部件上调用 paint() 函数时。

      【讨论】:

        【解决方案3】:

        我自己找到了一个简单的解决方案:

        不是从 QWidget 派生,而是从 QQuickPaintedItem 派生。 QQuickPaintedItem 是一个完全满足我需要的类:使用 QPainter 在 QML-Element 上绘画。这是代码(缩小到基本部分):
        mfcanvas.h:

        class MFCanvas : public QQuickPaintedItem
        {
            Q_OBJECT
        public:
            explicit MFCanvas(QQuickItem *parent = 0);
            ~MFCanvas();
        
        protected:
            void paint(QPainter *painter);
        

        mfcanvas.cpp:

        void MFCanvas::paint(QPainter *painter)
        {
            painter->translate(-translation.x(), -translation.y());
            //...
        }
        

        如您所见,提供了一个简单的paint() 函数,它传递一个指向QPainter 的指针,准备使用。 =)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-25
          • 1970-01-01
          • 1970-01-01
          • 2021-10-09
          • 2017-02-02
          相关资源
          最近更新 更多