簡體   English   中英

Qt:QWidget :: paintEngine:不應再被調用了

[英]Qt: QWidget::paintEngine: Should no longer be called

我正在嘗試創建一個應用程序,您可以用手指在畫布上繪制。
為了實現這一點,我將QWidget子類化為MFCanvas ,在QML中注冊了該類
qmlRegisterType<>() ,實現虛擬paintEvent(); 功能,和
paintEvent();使用QPainter繪制它paintEvent(); 功能。

問題:
在施工時, 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);
            }
        }
    //...
    }
}

如果您需要任何其他信息,請告訴我。
先感謝您! =)

這里很好地解釋了這一點:

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

簡而言之:不要嘗試直接從輸入事件處理程序繪制,而是重載窗口小部件中的paintEvent方法,然后在那里創建QPainter。 僅使用輸入事件來修改內部數據模型,並使用paintEvent中的QPainter在輸出路徑上顯示它。

在你的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: Should no longer be called它使它非常直接。 線條

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

可能表明這個畫家的QPaintDevice(如QPaintDevice::paintEngine )沒有提供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:

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

如您所見,提供了一個簡單的paint()函數,該函數將指針交給QPainter,隨時可以使用。 =)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM