“当下即永恒”  --- 佚名


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对应的节点的子节点了。

  1. 自定义的类需要继承自QQuickItem
  2. 需要自己实现QQuickItem的虚函数QQuickItem::updatePaintNode

  3. 需要设置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();
}

例子中,还有一些点需要继续探索:

  1. 重新实现的继承自QQuickItem类的void keyPressEvent函数并没有被触发,需要进一步看资料。
  2. 在main.qml中调用selfDefined.changeColor()时,会报错:TypeError: Cannot call method 'changeColor' of null,为什么找不到对象selfDefined呢,可能是将这个类放在qml中使用时有些地方需要注意。最好的方式是,看一下qt源码中的QQuickRectangle是如何实现的。

最新文章

  1. python征程1.3(初识python)
  2. Linux svn的搭建与使用
  3. Android中ListView的各种显示效果
  4. jQuery中的Ajax几种请求方式
  5. Dynamic CRM 2013学习笔记(七)追踪、监控及性能优化
  6. HTML5[6]:多行文本显示省略号
  7. Android 简单计算器源码....
  8. Xamarin 示例Standard Controls报错:xamarin Failed to compile interface file. See Build Output for details
  9. GIT之二 基础篇(2)
  10. 伪装隐藏Nginx,PHP版本号提升服务器安全性
  11. dnw for linux: Ubuntu下可用,无需编译驱动,mini2440可用
  12. iptables阻止服务器被攻击
  13. PHP扩展开发(1)-创建基础框架
  14. NBA工资帽
  15. pthread 简要使用指南
  16. Net线程安全集合
  17. Git 初学
  18. Spring Cloud的Zuul的使用问题
  19. TCP的代码
  20. 约数,gcd,exgcd.

热门文章

  1. intellij高亮字体背景颜色
  2. MySql数据封装操作类
  3. Wiki with Herbal Medicine
  4. junit4的初级用法
  5. 笨办法学Python
  6. OI歌曲汇总
  7. php Web 项目的文件/文件夹上传下载
  8. [RN] React Native 使用 FlatList 实现九宫格布局 GridList
  9. nbbnbnbnbnb
  10. Markdown 打出上下标