首页 > 技术文章 > QML之基于QML封装动态库组件

shHome 2020-12-14 06:16 原文

前言

在实际中的开发中,我们总是不希望自己的代码能被用户看到,但是使用QML文件封装的组件进行界面开发时,我们的QML源代码是会被编译器直接编译到.exe 或者 .elf 可执行文件中的,最过分的是,我们在QML中写的注释都会被原封不动的被编译到可执行文件中,供QML动态编译类去动态的执行编译或其他处理。
简直是叔叔能忍,嫂嫂不能忍,于是我就想着能把QML封装成动态库就好了,要想知道Qt Quick能不能搞,最直接的、最快速的方法就是看它的库结构或目录及源代码,毕竟别个开源了,不能浪费别个的一片苦心撒,于是我们发现在Qt Quick模块中,QML组件被普遍的编译成动态库的形式供开发者使用,为什么我们不这样弄呢?

注意
  • 你需要知道在Qt Quick中的动态库封装效果:
/*最终的封装组件库目录 > 
 * plugins.qmltypes   >> 让Qt的IDE能高亮我们自定义的组件
 * qmldir             >> 说明当前封装的组件信息,如[模块名],[插件名],[类型说明文件]
 * plugin.dll         >> release 版本的动态库
 * plugind.dll        >> debug 版本的动态库
 */
  • 你需要认真阅读与红色相似颜色的内容

  • 因为我在操作的过程中遇到一些问题,所以这篇随笔将详细的记录所有步骤。我也会将自己的理解标注在随笔中。

文章目录
0x01 创建Qt Quick Extension Plugin项目
  0x01-1 新建项目选择 Library --Qt Quick 2 Extension Plugin

  0x01-2 输入项目属性值

  [input] -项目名称 QmlAssembly
  [input] -项目路径 随意填写,与我们最终想要的效果没有关系

  0x01-3 配置项目细节

  [input] -Object class-name 随便填
  [input] -URL com.mycompany.qmlcomponents

  0x01-3 配置项目工具箱

  [select] 勾选 MinGW-32
  [select] 勾选 MinGW-64

0x02 配置自定义的组件参数
  0x02-1 添加自定义.qml组件 MyRect.qml MyRect2.qml
// MyRect.qml
import QtQuick 2.0

Rectangle {

    border.color: "red"
}

-------------------------------------------------------------------------

// MyRect2.qml
import QtQuick 2.0

Rectangle {

    border.color: "blue"
}
  0x02-2 删除自动生成的Object class-name名 .h .cpp 文件

  我这里是默认Object class-name名,所以我这里是删除 myitem.h myitem.cpp 文件

  0x02-3 添加注册的自定义QML组件
// void registerTypes(const char *uri) override
// 重写这个方法,并把自定义的QML组件注册到 URL 中
void QmlAssemblyPlugin::registerTypes(const char *uri)
{
    // @uri com.mycompany.qmlcomponents
    // param QUrl("qrc:/xxxx.qml") 是自定义组件的.qml文件地址
    // param 注册到URL
    // param 主版本号
    // param 次版本号
    // param 外部使用的类型名
    qmlRegisterType(QUrl("qrc:/MyRect.qml"), uri, 1, 0, "MyRect");
    qmlRegisterType(QUrl("qrc:/MyRect2.qml"), uri, 2, 0, "MyRect");
}
  0x02-4 编译并创建最终库目录
// 我们的自定义的组件动态库如果存放地址为 F:/Library/QmlAssembly
// Step 1 >> 在 F:/Library/QmlAssembly 目录下创建 com/mycompany/qmlcomponents/ 多级目录
// Step 2 >> 将编译后的 `debug` `release` `qmldir` 文件复制到 F:/Library/QmlAssembly/com/mycompany/qmlcomponents/ 目录下
  0x02-5 自动生成 .qmltype 文件

  qmlplugindump >> 自动生成 .qmltype 文件
  我们编译后,如果是 MinGW-32 编译的就打开 mingw73_32控制台,如果是 MinGW-64 编译的就打开 mingw73_64控制台

// param 项目中的 url
// param 版本号
// param 导出 `debug` `release` `qmldir` 文件的url路径
// param 导出的 `qmltype` 文件的存储路径
cmd >> `qmlplugindump com.mycompany.qmlcomponents 1.0 F:/Library/Qt/QmlAssembly > F:/Library/Qt/QmlAssembly/com/mycompany/qmlcomponents/mymodule.qmltype`

/*
// mymodule.qmltype
import QtQuick.tooling 1.2

// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
// 'qmlplugindump com.mycompany.qmlcomponents 1.0 F:/Library/Qt/QmlAssembly'

Module {
    dependencies: ["QtQuick 2.12"]
    Component {
        prototype: "QQuickRectangle"
        name: "MyRect 2.0"
        exports: ["MyRect 2.0"]
        exportMetaObjectRevisions: [0]
        isComposite: true
        defaultProperty: "data"
    }
    Component {
        prototype: "QQuickRectangle"
        name: "MyRect 1.0"
        exports: ["MyRect 1.0"]
        exportMetaObjectRevisions: [0]
        isComposite: true
        defaultProperty: "data"
    }
}

*/
  0x02-6 将自动生成的 .qmltype 文件信息链接到 qmldir 文件内
// 添加 >> typeinfo mymodule.qmltype
0x03 测试QML动态库
/*
Step 1 >> 创建一个纯净的QML的App项目
Step 2 >> 在 main.cpp 12 行添加 --engine.addImportPath("F:/Library/Qt/QmlAssembly/");
Step 3 >> 在main.qml中导入自定义QML组件库 --import com.mycompany.qmlcomponents 1.0
Step 4 >> 添加自定义的组件 MyRect
*/

main.qml 代码截图

com.mycompany.qmlcomponents 1.0 运行效果图

com.mycompany.qmlcomponents 2.0 运行效果图

总结
  • QML组件库封装的 URL 项必须在文件系统中展开,如 URL >> com.mycompany.qmlcomponents 在文件系统中就是 com/mycompany/qmlcomponents
  • 在QML的App项目中使用自定义QML库封装组件,必须通过 QQmlApplicationEngine::addImportPath() QML_IMPORT_PATH 导入到该项目才能使用
  • 如果你不能正常的自动生成 .qmltype 文件,那么你的关注点应该在 0x02-3 0x02-4 0x02-5,因为这几个点都可能会影响 .qmltype 文件能否正常的被生成

推荐阅读