Qt使用C++封装qml自定义图形控件(QQuickPaintedItem)
C++封装qml自定义图形控件QtWidget、qml简介通过继承QQuickPaintedItem封装控件描述公用接口定义代码示例效果图QtWidget、qml简介Qt提供了2套UI模式,分别是c++为主的代表Qt Widget,还有一套是qt quick。QtWidget已经相对很稳定了,控件丰富,所以一些大型项目也可得心应手。qml做的界面比较美观,可以简单的写出一些炫酷的动画和特效,对触屏
C++封装qml自定义图形控件
QtWidget、qml简介
Qt提供了2套UI模式,分别是c++为主的代表Qt Widget,还有一套是qt quick。
QtWidget已经相对很稳定了,控件丰富,所以一些大型项目也可得心应手。
qml做的界面比较美观,可以简单的写出一些炫酷的动画和特效,对触屏支持比较友好。比较适合做移动端开发,但是对于一些大型hua项目,界面复杂的个人认为还是用QtWidget好一点。qt quick默认是用opengl做图形渲染引擎。一般qquick项目,qml写界面,c++做功能后端。
今天我们要讲的是如何使用c++给qml封装自定义的图形控件。
通过继承QQuickPaintedItem封装控件
描述
QQuickPaintedItem使QPainter API与QML场景图一起使用成为可能。它在场景图中设置一个带纹理的矩形,并使用QPainter在纹理上绘制。渲染目标可以是一个QImage,或者在使用OpenGL时,是一个QOpenGLFramebufferObject。当渲染目标是一个QImage时,QPainter首先渲染到图像中,然后将内容上载到纹理中。当使用QOpenGLFramebufferObject时,QPainter直接在纹理上绘制。调用update()触发重绘。
若要启用QPanter进行抗锯齿渲染,请使用setAntialiasing()。
要编写自己绘制的项,首先要创建QQuickPaintedItem的子类,然后从实现其唯一纯虚拟公共函数paint()开始,该函数实现实际绘制。绘制将位于从0,0到width(),height()的矩形内。
公用接口定义
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()) |
这次起到关键作用的函数是主角 virtual void paint(QPainter *painter)=0,通过重写虚函数paint,实现要画的内容。
代码示例
下面实现一个图片显示的控件,滑动鼠标滚轮可实现图片的放大和缩小。
定义类XImageView,继承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
paint函数重写实现自绘
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);
}
注意:调用之前要先注册qml类型。
int verMajor = 1;
int verMinor = 0;
qmlRegisterType<XImageView>("custom.qimi.image",verMajor,verMinor,"XImageView");
qml调用示例
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();
}
}
效果图
滑动鼠标中间滚轮实现放大缩小:
结语:通过以上方法,我们可以实现qml各种不同控件的自定义。
完整代码示例:示例代码下载链接
作者:费码程序猿
欢迎技术交流:QQ:255895056
转载请注明出处,如有不当欢迎指正
更多推荐
所有评论(0)