QML学习笔记(十四)QML的自定义模块

前言

在前面的学习中,我们已经学会了自定义组件的实现方式,并通过属性暴露来让外部进行调用和交互。但只是这种程度还不足以满足我们实际开发的需求,为了实现定制组件的更好管理,我们需要引入模块的概念。

(在我学习的视频中,主要讲述了QT6+cmake的方法,但无奈我当前是QT5,所以我接下来只记录我学习QT5+qmake的模块实现)

一、前期准备

在正式学习之前,我们先准备我们的一系列文件。

新建工程QmlCustomModules,然后先在main.qml的同目录下,创建一个custom_buttons文件夹。

然后我们将之前的MButton.qml移动进去,并拷贝三个单独的按钮组件,分别为RedButton.qml、GreenButton.qml和BlueButton.qml。注意文件命名最好大写开头,至于里面的颜色修改,你懂的,代码我就只放红色按钮的上来吧。

最后把MButton改成GreyButton。

cpp 复制代码
import QtQuick 2.0

Item{
    id: rootId
    property alias buttonText: buttonTextId.text
    property alias buttonColor: containerRectId.color
    width: containerRectId.width
    height: containerRectId.height

    signal buttonClicked

    Rectangle {
        id: containerRectId
    //        width: 100
    //        height: 30
        width: buttonTextId.implicitWidth + 10
        height: buttonTextId.implicitHeight + 10
        color: "red"
        border{
            color: "black"
            width: 3
        }

        Text {
            id: buttonTextId
            text: qsTr("Button")
            anchors.centerIn: parent
        }

        MouseArea {
            id: mouseAreaId
            anchors.fill: parent
            onClicked: {
//                console.log("Clicked on the button")
                rootId.buttonClicked()
            }
        }
    }
}

一、QML Dir

在QT5阶段想要实现模块,需要依赖QML Dir文件,它是一种文本描述,用于说明我们的QML模块由哪些内容组成。

我们创建一个文本文件,并改名为qmldir,这里注意把txt后缀名也删掉,但后续打开时通用以记事本形式打开即可。

往里面写入文本描述:

cpp 复制代码
module custom_buttons
BlueButton 1.0 BlueButton.qml
RedButton 1.0 RedButton.qml
GreenButton 1.0 GreenButton.qml
GreyButton 1.0 GreyButton.qml

第一行是模块名称,module custom_buttons,这个名称必须和文件夹名称相同。

后面几行就可以设置模块名、版本和对应的qml文件,让我们遵循命名一致的规则。

二、导入模块

我们先将这些文件全部添加到qml.qrc中(右键,添加现有文件)。

最后就变成这样:

然后我们打开工程的pro文件,注意到这里的两行:

直接翻译一下:

cpp 复制代码
# 在Qt Creator的代码模型中用于解析QML模块的额外导入路径
QML_IMPORT_PATH =

# 仅为Qt Quick Designer解析QML模块时使用的额外导入路径
QML设计器导入路径 =

显然,我们需要对QML_IMPORT_PATH 进行设置,添加$PWD,这个东西代表当前目录。

最后,我们还要添加一行这个:

cpp 复制代码
DISTFILES += custom_buttons/qmldir

这里就用到了刚才准备的qmldir。

再然后,我们尝试引用模块,发现会报错,模块未安装。

那是因为,我们需要对main.cpp中的引擎添加导入路径。

cpp 复制代码
engine.addImportPath("qrc:/");

三、运行程序

成功能看到四个按钮,证明导入成功。

四、解决红字报错

到这里其实就已经结束,能够正常使用了。

但我对这句报错很不爽,明明都能成功运行了,为什么好像工程识别不出来一样。

最终问题是在pro中的这一句:

cpp 复制代码
QML_IMPORT_PATH = $PWD

我们修改成:

cpp 复制代码
QML_IMPORT_PATH += $$PWD

这里的修改点是使用了+=追加的方式,不要覆盖原本的路径。然后使用了$$,不要使用$

我问了一下kimi同学,它给了我如下总结:

一句话记: "= 是覆盖,+= 是追加;$$ 是 qmake 内建,$ 是 shell 变量。"

写法 作用域 结果 对 Creator 高亮
QML_IMPORT_PATH = $PWD 只在qmake运行期被 shell 展开 清空原路径,再塞一条展开后的绝对路径 静态分析认不得 $PWD仍标红
QML_IMPORT_PATH += $$PWD qmake + Creator 都识别 原路径保留,再追加一条 $$PWD 解析器能找到 $$PWD/Custombuttons/qmldir高亮正常

结论:
永远用 += $$PWD,既追加又跨平台,让运行期和高亮期同时满意。

简单来说就是Creator 的语法高亮引擎不认识$PWD,所以会标红。

五、总结

在学习本节之前,我其实就有疑问了 ,如果我们自定义组件越来越多,我是否能通过一个文件夹来进行存放。而且组件越来越多的话,我要怎么进行引用,总不能全部都import一遍吧。

而本节给了我答案,可以通过模块的方式去进行加载。可以看到我们一起import就可以使用到多个组件,其形式就跟c++的封装一样,十分方便和有趣。

相关推荐
练习时长一年2 小时前
ApplicationContext接口实现(二)
java·开发语言
wdfk_prog3 小时前
[Linux]学习笔记系列 -- lib/sort.c 通用的排序库(Generic Sorting Library) 为内核提供标准的、高效的排序功能
linux·运维·c语言·笔记·stm32·学习·bug
灵性花火3 小时前
针对多工程情况下,Qwidget的ui文件的Stylesheet找不到图片的问题
开发语言·qt
tpoog3 小时前
[C++项目组件]cpp-httplib与 websocketpp的简单介绍和使用
开发语言·c++
GISer_Jing3 小时前
0926第一个口头OC——快手主站前端
开发语言·前端·javascript
风语者6663 小时前
perl踩坑系列===正则表达式第2坑---split中的“或”操作符
开发语言·正则表达式·perl
狂团商城小师妹4 小时前
JAVA露营基地预约户外露营预约下单系统小程序
java·开发语言·微信小程序·小程序
CappuccinoRose4 小时前
MATLAB学习文档(二十二)
学习·算法·matlab
大飞pkz4 小时前
【设计模式】策略模式
开发语言·设计模式·c#·策略模式