【写在前面】
在 QML6 开发中,每个 QML 文档都默认具有隐式导入。
这意味着我们可以在同一目录下使用其他 QML 文档,而无需显式导入,这大大减少了编写冗余代码的工作量。通常,我们不需要为 QML 文件所属的模块进行导入。
然而,如果隐式导入不能识别文件所属的模块,这一功能的价值就会大打折扣。
虽然理论上这种情况不会发生,但由于 Cmake API 的限制,我们不能完全排除这种可能性。
【正文开始】
-
项目结构与隐式导入的关系
有些人可能会尝试绕过 Cmake API 对 QML 模块的使用,这可能会导致一些问题。例如,如果你的项目结构如下所示:
在这种情况下,main.qml
和 Pickles.qml
的隐式导入是 qml
目录,而它们的模块定义在 myProject
目录。如果你想在 main.qml
或 Pickles.qml
中使用 some_qml_type.h
定义的内容,你需要显式导入 myproject
模块。
为什么会这样?原因在于,如果没有 qmldir
文件,隐式导入只会根据文件名构建QML文件的类型名,而不会考虑 C++ 定义的类型。
-
通过 CMakeLists.txt 调整类型名称
通过在 CMakeLists.txt
中添加以下内容:
set_source_files_properties(qml/Pickles.qml PROPERTIES QT_QML_SOURCE_TYPENAME Chocolate)
在 main.qml
中,你可以像以前一样使用名为 "Pickles" 的组件。但是,如果导入了 myproject
,你将得到一个名为 "Chocolate" 的组件,它具有相同的内容。由于 Main.qml
没有导入 myproject
,它不会识别 "Chocolate" 组件。这是一个有趣的现象。
-
解决方案与最佳实践
为了解决这个问题,我们可以采取以下几种方法:
1、移动 QML 文件:将 QML 文件移动到更高层次的目录,并消除 "qml" 子目录。这是最简单的方法,但也意味着放弃了 QML 与 C++ 代码的内部分离。
2、定义多个 QML模 块:在顶级目录定义一个 QML 模块 "myProject",然后在 "qml" 子目录定义另一个名为 "myProject.qml" 的 QML 模块。这样,如果你想使用其中一个模块中的类型,你需要显式导入。
3、明确导入模块:在每个文件中显式导入你自己的模块。确保模块可以在导入路径中找到,并且明确定义了导入路径。
最后,注意到一个错误:如果你的模块没有插件,你正在使用其组件之一作为入口点,且 QML 文件加载在模块的基本目录中,那么模块的 C++ 定义类型将不会从隐式导入中加载,而这是一个 BUG。
【结语】
总之,了解QML模块和隐式导入的关系对于QT开发至关重要。通过采取适当的项目结构和明确的导入策略,我们可以确保代码的清晰性和功能性。