簡體   English   中英

QQuickPaintedItem的繪制方法未調用

[英]Paint method of QQuickPaintedItem not called

我有一個要在QML中實例化的C ++ QQuickPaintedItem。 但是,從來不會調用paint()方法。

這是我的代碼:

CPlotXY.h

#ifndef CPLOTXY_H
#define CPLOTXY_H

#include <QQuickPaintedItem>
#include <lib/qcustomplot-source/qcustomplot.h>
#include <QQuickView>

class CPlotXY : public QQuickPaintedItem
{
    Q_OBJECT
    public:
        CPlotXY(QQuickItem* parent = 0);
        virtual ~CPlotXY();

        void paint(QPainter* painter);

        Q_INVOKABLE void init();

    protected:
        void routeMouseEvents( QMouseEvent* event );

        virtual void mousePressEvent( QMouseEvent* event );
        virtual void mouseReleaseEvent( QMouseEvent* event );
        virtual void mouseMoveEvent( QMouseEvent* event );
        virtual void mouseDoubleClickEvent( QMouseEvent* event );

        void setupQuadraticDemo( QCustomPlot* Q_CustomPlot );

    private:
        QCustomPlot*         Q_CustomPlot;

    private slots:
        void graphClicked( QCPAbstractPlottable* plottable );
        void onCustomReplot();
        void updateCustomPlotSize();

};

#endif // CPLOTXY_H

CPlotXY.cpp

#include "CPlotXY.h"

CPlotXY::CPlotXY( QQuickItem* parent ) : QQuickPaintedItem( parent ), Q_CustomPlot( nullptr )
{
    setFlag( QQuickItem::ItemHasContents, true );
    setAcceptedMouseButtons( Qt::AllButtons );
    connect( this, &QQuickPaintedItem::widthChanged, this, &CPlotXY::updateCustomPlotSize );
    connect( this, &QQuickPaintedItem::heightChanged, this, &CPlotXY::updateCustomPlotSize );
}

CPlotXY::~CPlotXY()
{
    delete Q_CustomPlot;
    Q_CustomPlot = nullptr;
}

void CPlotXY::init()
{
    Q_CustomPlot = new QCustomPlot();

    updateCustomPlotSize();

    setupQuadraticDemo( Q_CustomPlot );

    connect( Q_CustomPlot, &QCustomPlot::afterReplot, this, &CPlotXY::onCustomReplot );

    Q_CustomPlot->replot();

}


void CPlotXY::paint(QPainter* painter)
{
    qDebug() << "@####";
    if (Q_CustomPlot)
    {
        QPixmap    Q_PixMap( boundingRect().size().toSize() );
        QCPPainter Q_CPPainter( &Q_PixMap );

        Q_CustomPlot->toPainter(&Q_CPPainter);

        painter->drawPixmap(QPoint(), Q_PixMap);
    }
}

void CPlotXY::mousePressEvent( QMouseEvent* Q_Event )
{
    qDebug() << Q_FUNC_INFO;
    routeMouseEvents( Q_Event );
}

void CPlotXY::mouseReleaseEvent( QMouseEvent* Q_Event )
{
    qDebug() << Q_FUNC_INFO;
    routeMouseEvents( Q_Event );
}

void CPlotXY::mouseMoveEvent( QMouseEvent* Q_Event )
{
    routeMouseEvents( Q_Event );
}

void CPlotXY::mouseDoubleClickEvent( QMouseEvent* Q_Event )
{
    qDebug() << Q_FUNC_INFO;
    routeMouseEvents( Q_Event );
}

void CPlotXY::graphClicked( QCPAbstractPlottable* Q_Plottable )
{
    qDebug() << Q_FUNC_INFO << QString( "Clicked on graph '%1 " ).arg( Q_Plottable->name() );
}

void CPlotXY::routeMouseEvents( QMouseEvent* Q_Event )
{
    if (Q_CustomPlot)
    {
        QMouseEvent* Q_NewEvent = new QMouseEvent( Q_Event->type(), Q_Event->localPos(), Q_Event->button(), Q_Event->buttons(), Q_Event->modifiers() );
        //QCoreApplication::sendEvent( m_CustomPlot, newEvent );
        QCoreApplication::postEvent( Q_CustomPlot, Q_NewEvent );
    }
}

void CPlotXY::updateCustomPlotSize()
{
    if (Q_CustomPlot)
    {
        Q_CustomPlot->setGeometry( 0, 0, width(), height() );
    }
}

void CPlotXY::onCustomReplot()
{
    qDebug() << Q_FUNC_INFO;
    update();
}

void CPlotXY::setupQuadraticDemo( QCustomPlot* customPlot )
{
    // make top right axes clones of bottom left axes:
    QCPAxisRect* axisRect = customPlot->axisRect();

    // generate some data:
    QVector<double> x( 101 ), y( 101 );   // initialize with entries 0..100
    QVector<double> lx( 101 ), ly( 101 ); // initialize with entries 0..100
    for (int i = 0; i < 101; ++i)
    {
        x[i] = i / 50.0 - 1;              // x goes from -1 to 1
        y[i] = x[i] * x[i];               // let's plot a quadratic function

        lx[i] = i / 50.0 - 1;             //
        ly[i] = lx[i];                    // linear
    }
    // create graph and assign data to it:
    customPlot->addGraph();
    customPlot->graph( 0 )->setPen( QPen( Qt::red ) );
    //customPlot->graph( 0 )->setSelectedPen( QPen( Qt::blue, 2 ) );
    customPlot->graph( 0 )->setData( x, y );

    customPlot->addGraph();
    customPlot->graph( 1 )->setPen( QPen( Qt::magenta ) );
    //customPlot->graph( 1 )->setSelectedPen( QPen( Qt::blue, 2 ) );
    customPlot->graph( 1 )->setData( lx, ly );

    // give the axes some labels:
    customPlot->xAxis->setLabel( "x" );
    customPlot->yAxis->setLabel( "y" );
    // set axes ranges, so we see all data:
    customPlot->xAxis->setRange( -1, 1 );
    customPlot->yAxis->setRange( -1, 1 );

    customPlot ->setInteractions( QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables );
    connect( customPlot, SIGNAL( plottableClick( QCPAbstractPlottable*, QMouseEvent* ) ), this, SLOT( graphClicked( QCPAbstractPlottable* ) ) );
}

XPlotXY.qml

import QtQuick 2.0
import CPlotXY 1.0

Item {
    CPlotXY {
        id: customPlot
        anchors.fill: parent
        Component.onCompleted: init()
    }
}

最后,這是我實例化的時候:

Repeater {
    id: widgetRepeater
    model: pageModel
    anchors.fill: parent
    delegate: Loader {



        property int modelX: model.XPos
        property int modelY: model.YPos
        //property int modelWidth: model.width
        //property int modelHeight: model.height

        active: true;
        asynchronous: true
        //anchors.centerIn:  parent
        source: "%1.qml".arg(model.Type)
    }
}

調用CPlotXY的init()函數並創建對象,但從不調用paint()方法。 我知道解決方案很明顯,但是我對QQuickPaintedItem不滿意。

感謝您的幫助。

我認為這個最小的示例將重現您的問題:

// mypainteditem.h

#ifndef MYPAINTEDITEM_H
#define MYPAINTEDITEM_H

#include <QObject>
#include <QQuickPaintedItem>

class MyPaintedItem : public QQuickPaintedItem
{
    Q_OBJECT
public:
    MyPaintedItem(QQuickItem* parent = nullptr);


    void paint(QPainter* painter);
};

#endif // MYPAINTEDITEM_H

// mypainteditem.cpp

#include "mypainteditem.h"
#include <QDebug>

MyPaintedItem::MyPaintedItem(QQuickItem* parent)
    : QQuickPaintedItem(parent)
{

}


void MyPaintedItem::paint(QPainter *painter)
{
    qDebug() << "Paint called";
}

// main.qml(將MyPaintedItem注冊為PaintItem

import QtQuick 2.7
import QtQuick.Window 2.1
import PaintItem 1.0

Window {
    id:rootWindow
    visible: true
    width: 800
    height: 600
    title: qsTr("Test")

    PaintItem {
    }
}

如您所見:不會調用paint -method。 問題是:我們沒有PaintItem大小,因此它是不可見的。 為了避免不必要的paint呼叫,我們不稱之為。

更改大小將產生繪畫效果:

import QtQuick 2.7
import QtQuick.Window 2.1
import PaintItem 1.0

Window {
    id:rootWindow
    visible: true
    width: 800
    height: 600
    title: qsTr("Test")

    PaintItem {
        id: pi
        height: width
    }

    Timer {
        interval: 2000 // Set some dimensions after 2 seconds will produce the paint call.
        onTriggered: pi.width = 100;
        running: true
    }
}

如果可能出現問題,為什么您的圖表大小為0 ...

  • 在您的文件XPlotXY.qml您(出於某些原因)將繪圖包裝在一個Item使該繪圖填充該Item

  • main.qml ,創建一個填充窗口的Repeater 但是, Repeater不會調整其委托的大小。 它僅實例化它們。

  • RepeaterdelegateLoader 如果未設置顯式大小,則Loader根據其內容調整其大小。 那么它加載了什么呢? 可能您的XPlotXY.qml沒有設置大小。 因此, Loader和繪圖的大小最終為0

暫無
暫無

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

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