Qt5 QtQuick系列----QtQuick的Secne Graph剖析(2)--自定义QML类型 (继承QQuickItem)
“当下即永恒” --- 佚名
Qt用户可以方便地使用QML中的Rectangle等基本类型,但是当不够用时,或,需要开发更高级的界面时,可以自己定义QML类型。
自定义QML类型需要继承自QQuickItem类,首先,需要了解这个类:http://doc.qt.io/qt-5/qquickitem.html 官方文档讲得很清楚:
“The QQuickItem class provides the most basic of all visual items in Qt Quick.
All visual items in Qt Quick inherit from QQuickItem. Although a QQuickItem instance has no visual appearance, it defines all the attributes that are common across visual items, such as x and y position, width and height, anchoring and key handling support.
You can subclass QQuickItem to provide your own custom visual item that inherits these features.”
QML中的Item元素与C++中的QQuickItem类对应。
基本上所有的基本qml类型都可以通过用户继承QQuickItem来自己实现吧。实现自定义qml类型,需要注意以下几点:
函数的作用:允许你自己在函数内部定义QSGNode结构,允许你自己定义一个subtree,最后返回这个subtree的根节点。 在显示qml到屏幕的流程中(参考我的博文:https://blog.csdn.net/qq_35865125/article/details/86485008 ),qml最终会被转换成一个树,树的节点是QSGNode类型的,对于已经存在的qt给我们定义的qml基本类型,例如Rectangle,它们应该也是通过调用自己的updatePainNode来实现将自己转换成QSGNode的,只不过是qt公司的人帮我们写好了,这里我们自己定义节点的话,就需要自己实现这个函数了。另外,这个函数返回的QSGNode*是会被自动加入到一个更大的树结构中的。例如,你自己实现了一个类型myQMLType,然后,你在文件中将其放在一个Rectangle内部,于是乎你自己定义的这个类型对应的节点就是Rectangle对应的节点的子节点了。
- 自定义的类需要继承自QQuickItem。
- 需要自己实现QQuickItem的虚函数QQuickItem::updatePaintNode
- 需要设置QQuickItem::ItemHasContents标记。
我一般在在构造函数中进行设置:setFlags(QQuickItem::ItemHasContents); 只有设置了这个标记,你自己定义的updatePainNode才可以被自动执行。
从上面两处截图可以知道,设置了标识之后,QQuickItem::update才能够被调用,这个函数会最终导致你自己实现的updatePainNode函数被调用。
4) 需要调用qmlRegisterType函数来将你自己定义的c++类型注册到QML环境中,并在qml文件中机型import才能在qml文件中直接使用。
e.g:在main函数中: qmlRegisterType<SelfDefinedQMLType>("SelfDefinedQMLType", 1, 0, "SelfDefinedQMLType");
在qml文件中: import SelfDefinedQMLType 1.0
5)要弄清楚资源清理方式:
例如,在下面我给出的例子中,如果在析构函数中调用delete QSGSimNode,会报错,应该是qt会自动处理这个资源,无需手动。
5)要认识到QQuickItem类中有很多函数的,例如QQuickItem::keyPressEvent函数,可以在你的子类中重新实现这个函数,处理按键消息。具体可以自己细看官方文档。
6) 单独的QquickItem并不能单独被显示,需要借助QquickWindow来显示。--一个qml文件中包含很多个Rectangle,text等基本组件,它们对应的C++类都继承自quick的最基本类:QQuickItem,这些个qml文件中的控件被组织成一个树结构,树的每个节点的类型都可以看成是QQuickItem,然后,这个树由 QquickWindow负责显示出来,主要是 通过调用底层opengl渲染出来(渲染的过程一般是一个单独的线程。)::
请看下面的一个我的例子:(或许官网上还有其他更好的例子)
网盘:
自定义的类,头文件:
#ifndef SELFDEFINEDQMLTYPE_H
#define SELFDEFINEDQMLTYPE_H
#include <QSGSimpleRectNode>
#include <QtQuick/QQuickItem>
class SelfDefinedQMLType: public QQuickItem
{
Q_OBJECT
public:
SelfDefinedQMLType();
~SelfDefinedQMLType();
Q_INVOKABLE void changeColor();
protected:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *);
void keyPressEvent(QKeyEvent *event);
private:
QSGSimpleRectNode* QSGSimNode;
};
#endif // SELFDEFINEDQMLTYPE_H
自定义的类,cpp:
#include "SelfDefinedQMLType.h"
SelfDefinedQMLType::SelfDefinedQMLType()
{
setFlags(QQuickItem::ItemHasContents);
QSGSimNode = NULL;
//setFocus(true);
qDebug()<<"SelfDefinedQMLType::SelfDefinedQMLType() was called!";
}
SelfDefinedQMLType::~SelfDefinedQMLType()
{
qDebug() << "SelfDefinedQMLType::~SelfDefinedQMLType start";
if(QSGSimNode)
{
//Must comment the following, otherwise, there will be an error!
//seems that the qt can handle resource itself.
//delete QSGSimNode;
}
qDebug() << "SelfDefinedQMLType::~SelfDefinedQMLType end";
}
void SelfDefinedQMLType::changeColor()
{
if (!QSGSimNode) {
if( QColor(255, 0, 0, 127) == QSGSimNode->color() )
QSGSimNode->setColor(QColor(255, 0, 0, 127));
else
QSGSimNode->setColor(QColor(0, 255, 0, 127));
}
}
QSGNode *SelfDefinedQMLType::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
//define a rectangle:
QSGSimNode = static_cast<QSGSimpleRectNode *>(node);
if (!QSGSimNode) {
QSGSimNode = new QSGSimpleRectNode();
QColor myColor = QColor(255, 0, 0, 127);
QSGSimNode->setColor(myColor);
QSGSimNode->setRect(10,10,400,400);
}
return QSGSimNode;
}
//why: this func can not be activated, even add "setFocus(true);" in SelfDefinedQMLType::SelfDefinedQMLType()
void SelfDefinedQMLType::keyPressEvent(QKeyEvent *event)
{
if(Qt::Key_Left == event->key())
changeColor();
}
main.qml
import QtQuick 2.11
import QtQuick.Window 2.11
import SelfDefinedQMLType 1.0
import QtQuick 2.4
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
Window {
id:windowTop
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
id:rect1
x:0
y:0
visible: true
anchors.fill: parent
color: "steelblue"
Keys.enabled: true
focus: true
SelfDefinedQMLType{
id:selfDefined
}
Keys.onPressed: {
switch(event.key)
{
case Qt.Key_Left:
console.log("Qt.Key_Left was pressed!!!")
//don't know why,the following repor error, during execution.
selfDefined.changeColor()//Error:TypeError: Cannot call method 'changeColor' of null
break;
}
}
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "SelfDefinedQMLType.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<SelfDefinedQMLType>("SelfDefinedQMLType", 1, 0, "SelfDefinedQMLType");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
例子中,还有一些点需要继续探索:
- 重新实现的继承自QQuickItem类的void keyPressEvent函数并没有被触发,需要进一步看资料。
- 在main.qml中调用selfDefined.changeColor()时,会报错:TypeError: Cannot call method 'changeColor' of null,为什么找不到对象selfDefined呢,可能是将这个类放在qml中使用时有些地方需要注意。最好的方式是,看一下qt源码中的QQuickRectangle是如何实现的。
Qt5 QtQuick系列----QtQuick的Secne Graph剖析(2)--自定义QML类型 (继承QQuickItem)的更多相关文章
- Qt5 QtQuick系列----QtQuick的Secne Graph剖析(1)
教是言词, 实不是道,道本无言, 言说是妄.------- 达摩 Qt 5提出了一个新的渲染底层,以替代Qt4时期的Graphics View,这个渲染底层就是Scene Graph.Scene Gr ...
- Qt5 QtQuick系列----QtQuick的Secne Graph剖析(3)-- qml与OpenGl结合
我读的书愈多,就愈亲近世界,愈明了生活的意义,愈觉得生活的重要. -- 高尔基 需要先看:https://blog.csdn.net/qq_35865125/article/details/86485 ...
- 【java集合框架源码剖析系列】java源码剖析之TreeSet
本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...
- 【java集合框架源码剖析系列】java源码剖析之HashSet
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于HashSet的知识. 一HashSet的定义: public class HashSet&l ...
- Gradle学习系列之九——自定义Task类型
在本系列的上篇文章中,我们学习了多Project构建,在本篇文章中,我们将学到如何自定义Task类型. 请通过以下方式下载本系列文章的Github示例代码: git clone https://git ...
- 【java集合框架源码剖析系列】java源码剖析之TreeMap
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于TreeMap的知识. 一TreeMap的定义: public class TreeMap&l ...
- 【java集合框架源码剖析系列】java源码剖析之ArrayList
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...
- 【java集合框架源码剖析系列】java源码剖析之LinkedList
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 在实际项目中LinkedList也是使用频率非常高的一种集合,本博客将从源码角度带领大家学习关于LinkedList的知识. ...
- 【java集合框架源码剖析系列】java源码剖析之HashMap
前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几 ...
随机推荐
- C#编写简单的聊天程序(转)
这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...
- Spring Security 3多用户登录实现之二 多登录界面展示
作者 接前讲,首先针对一个多种用户类型的登录需求,需要先实现多种用户类型的登录界面的展示,Spring Security提供了这样一个接口来帮助我们实现多种用户类型的登录界面的展示,这个接口就是Aut ...
- Django REST framework视图
混合类阶段(封装2次) 路由: url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', vie ...
- 决策树——ID3
参考网址:https://www.cnblogs.com/further-further-further/p/9429257.html ID3算法 最优决策树生成 -- coding: utf-8 - ...
- struct udphdr
udphdr结构包含在/usr/src/linux/include/linux/udp.h struct udphdr { __u16 source; __u16 dest; __u16 len; _ ...
- [xms]西软xms试算平衡报表-穿透明细报表-增加储值卡卡号列
只能呵呵哒 [xms]西软xms试算平衡报表-穿透明细报表-增加储值卡卡号列 pospay ' and hotelid='${hotelid}'; hhaccount ' and hotelid='$ ...
- jmeter5实现mysql数据库值提取--单sql提取
字段背景: 在进行接口测试或者压力测试过程中下文的请求需要用到上文请求的值,除了通过正则表达式的方式外,为了更准确的获得数据库值,我们可以直接从数据库提取 一.如何实现数据库的连接.此处不再赘述 点击 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-代码生成器用法
新的代码生成器比老的更加容易使用,要生成什么形式就选择什么形式,新的代码生成器采用的是WCF界面开发,同样采用开源的模式,根据自己使用习惯容易扩展 1.单列表模式 2.树形列表模式 3.左右列表模式 ...
- 块元素&行内元素
大多数HTML 元素被定义为块级元素或内联元素.块级元素在浏览器显示时,通常会以新行来开始(和结束) block元素特点 1 总是在新行上开始: 2 高度,行高以及外边距和内边距都可控制: 3 宽度缺 ...
- spring boot后端使用fastjson,错误代码415, 500
$.post({ url: "/register", dataType: "json", contentType: "application/json ...