Qt uses C++ to encapsulate qml custom graphics control (QQuickPaintedItem)

Introduction to QtWidget and qml

Qt provides 2 sets of UI modes, one is the representative Qt Widget based on C++, and the other is qt quick.
QtWidget is already relatively stable and has rich controls, so it can be used for some large-scale projects.
The interface made by qml is more beautiful, you can easily write some cool animations and special effects, and it is more friendly to touch screen support. It is more suitable for mobile terminal development, but for some large-scale Hua projects with complex interfaces, I personally think it is better to use QtWidget. Qt Quick uses OpenGL as the graphics rendering engine by default. In general qquick projects, qml writes the interface and C++ serves as the functional backend.
Today we are going to talk about how to use c++ to encapsulate custom graphic controls in qml.

Encapsulate controls by inheriting QQuickPaintedItem

describe

QQuickPaintedItem makes it possible to use the QPainter API with QML scene graphs. It sets up a textured rectangle in the scene graph and uses QPainter to draw on the texture. The render target can be a QImage, or when using OpenGL, a QOpenGLFramebufferObject. When the render target is a QImage, QPainter first renders into the image and then uploads the contents into the texture. When using QOpenGLFramebufferObject, QPainter draws directly on the texture. Calling update() triggers a redraw.
To enable QPanter for antialiased rendering, use setAntialiasing().
To write your own painted item, you first create a subclass of QQuickPaintedItem, and then start by implementing its only pure virtual public function, paint(), which implements the actual painting. The draw will be inside a rectangle from 0,0 to width(),height().

Public interface definition

QQuickPaintedItem(QQuickItem *parent = Q_NULLPTR)
virtual ~QQuickPaintedItem()
bool antialiasing() const
QColor fillColor() const
bool mipmap() const
bool opaquePainting() const
virtual void paint(QPainter *painter) = 0
PerformanceHints performanceHints() const
RenderTarget renderTarget() const
void setAntialiasing(bool enable)
void setFillColor(const QColor &)
void setMipmap(bool enable)
void setOpaquePainting(bool opaque)
void setPerformanceHint(PerformanceHint hint, bool enabled = true)
void setPerformanceHints(PerformanceHints hints)
void setRenderTarget(RenderTarget target)
void setTextureSize(const QSize &size)
QSize textureSize() const
void update(const QRect &rect = QRect())

The function that plays a key role this time is the protagonistvirtual void paint(QPainter *painter)=0, by overriding the virtual function paint, the content to be painted is realized.

code example

The following implements a control for image display. Sliding the mouse wheel can zoom in and out of the image.

Define class XImageView, inherit QQuickPaintedItem

#ifndef XIMAGEVIEW_H
#define XIMAGEVIEW_H

#include <QObject>
#include <QImage>
#include <QQuickPaintedItem>

class QPainter;
class XImageView : public QQuickPaintedItem
{
    
    
    Q_OBJECT

    Q_PROPERTY(QImage mImage READ getImage WRITE setImage)
    Q_PROPERTY(QString fileUrl READ getFileUrl WRITE setFileUrl)
    Q_PROPERTY(int mWidth READ getWidth WRITE setWidth)
    Q_PROPERTY(int mHeight READ getHeight WRITE setHeight)

public:
    XImageView(QQuickItem *parent = 0);
    virtual ~XImageView();

    virtual void paint(QPainter *painter);

    QImage getImage() const;
    void setImage(QImage img);

    QString getFileUrl() const;
    void setFileUrl(QString url);

    int getWidth() const;
    void setWidth(int w);

    int getHeight() const;
    void setHeight(int h);

    Q_INVOKABLE void zoomDraw(float z = 1.0f);

private:
   QImage mImage;
   QString fileUrl;
   int mWidth;
   int mHeight;
   float mZoom;
};

#endif // XIMAGEVIEW_H

Rewrite the paint function to implement self-painting

void XImageView::paint(QPainter *painter)
{
    
    
    if (painter == nullptr)
    {
    
    
        return;
    }
    if(mImage.isNull())
    {
    
    
        if(!fileUrl.isEmpty())
        {
    
    
            if(!mImage.load(fileUrl))
            {
    
    
                qDebug("load image file failed!");
                return;
            }
        }else
        {
    
    
            qDebug("file is not exsit!");
            return;
        }
    }

    QImage tempImage = mImage.scaled(mWidth*mZoom,mHeight*mZoom,Qt::KeepAspectRatio);

    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
    painter->setRenderHint(QPainter::SmoothPixmapTransform, true );
    painter->drawImage(0,0, tempImage);
}

Note: The qml type must be registered before calling.

    int verMajor = 1;
    int verMinor = 0;

    qmlRegisterType<XImageView>("custom.qimi.image",verMajor,verMinor,"XImageView");

qml call example

import QtQuick 2.9
import QtQuick.Window 2.2

import custom.qimi.image 1.0

Window {
    
    
    visible: true
    width: 480
    height: 800
    title: qsTr("QQuickPaintedItem Plugin 费马程序员 QQ:2558950565")

    property double zoomVlaue: 1.0
    signal drawImage()

    Rectangle
    {
    
    
        id: image
        color: "transparent"
        border.color: "red"
        anchors
        {
    
    
            margins: 0
            centerIn: parent
            fill: parent
        }  
    }

    XImageView
    {
    
    
        id: ximageView
        width: parent.width
        height: parent.height
        mWidth: parent.width
        mHeight: parent.height
        fileUrl: ":/image/mmm.jpg"
    }

    MouseArea
    {
    
    
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton
        onClicked: {
    
    
            if(mouse.button === Qt.LeftButton)
            {
    
    
                drawImage();
            }
        }
        onWheel: {
    
    
            var m_value = wheel.angleDelta.y/120;
            if(m_value>0)
            {
    
    
                if(zoomVlaue<1.0){
    
    
                zoomVlaue += 0.1;
                }
            }else
            {
    
    
                if(zoomVlaue>0.0){
    
    
                zoomVlaue -= 0.1;
                }
            }
            console.log("wheel event=,zoom=",m_value,zoomVlaue);
            ximageView.zoomDraw(zoomVlaue);
        }
    }

    onDrawImage: {
    
    
        console.log("mouse clicked!");
        ximageView.zoomDraw();
    }
}

renderings

Slide the middle mouse wheel to zoom in and out:
Insert image description here

Conclusion: Through the above methods, we can customize various qml controls.
Full code example: Sample code download link

Author: Feima Programmer.
Welcome to technical exchange: QQ: 255895056.
Please indicate the source for reprinting. If there is any inappropriateness, please correct me.

Guess you like

Origin blog.csdn.net/haohaohaihuai/article/details/106422652
Recommended