2014-09-11 37 views
2

我試圖製作一個應用程序,您可以用手指在畫布上繪製。爲了實現這一點,我將QWidget作爲MFCanvas的子類化,在QML中註冊該類,使用
qmlRegisterType <>(),實現虛擬paintEvent();函數,並在paintEvent()中使用QPainter在其上繪製它。功能。

問題:
在建設中,QPainter的拋出這樣的警告:
Qt:QWidget :: paintEngine:不應該再叫

QWidget::paintEngine: Should no longer be called 

然後,serveral的其他相關警告拋出:

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

難怪:在QPainter的沒」 t繪製任何東西...
此外,我應該調用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); 
      } 
     } 
    //... 
    } 
} 

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

回答

0

我已經找到了一個簡單的解決方案自己:

而是從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,隨時可以使用。 =)

1

在你mfcanvas.cpp,void MFCanvas::pressed(float x, float y)功能,行

paintEvent(NULL); 

似乎是令人不安的。嘗試了類似的代碼 - 我得到了同樣的錯誤。

提出的解決方案:使用this->repaint()this->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(如QPaintDevice::paintEngine)提供QPaintEngine。我們可以假定這個QPaintEngine是由繪圖設備自己生成或者調用的,例如,當在一個小部件上調用paint()函數時。

1

這是很好的解釋在這裏:

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

簡而言之:不要試圖從輸入事件處理程序直接, 作畫,但超載在你的插件的的paintEvent方法,而不是創造的 QPainter那裏。僅使用輸入事件修改內部數據模型,並在paintEvent中使用QPainter在輸出路徑上顯示它。

相關問題