QML- 导入库包语法
- 一、概述
- 二、Import语句的语法
- 1. Module (namespace) 模块(命名空间)导入
- 1. 非模块命名空间的导入
- 2. 导入到限定局部命名空间
- 2. 路径 import
- 1. 本地目录导入
- 2. 远程目录
- 3. JavaScript资源导入
- 三、QML导入路径
- 四、调试
一、概述
import 语句其实在QML文档里面体现的就是首部位置,和其他编程语言类似,import 语句允许客户端告诉引擎QML文档中使用了哪些模块、JavaScript资源和组件目录。文档中可能使用的类型取决于文档导入了哪些模块、资源和目录。
也很像 C++ 里面的 #include<xxx.h> 引入什么资源之类的。
二、Import语句的语法
qml 里面 有三种不同类型的导入。每种导入类型的语法略有不同,适用于不同导入类型的语义也不同。
1. Module (namespace) 模块(命名空间)导入
最常见的导入类型是模块导入。客户端可以导入QML模块,这些模块将QML对象类型和JavaScript资源注册到给定的命名空间中。
模块导入的一般形式如下:
import <ModuleIdentifier> <Version.Number> [as <Qualifier>]
- < ModuleIdentifier> 是一个以点分URI表示法指定的标识符,唯一地标识模块提供的类型命名空间。
- <Version.Number> 是MajorVersion.MinorVersion 形式的一个版本。\指定导入后将提供的各种对象类型和JavaScript资源的定义。
- < Qualifier> 是一个可选的局部命名空间标识符,模块提供的对象类型和JavaScript资源将被安装到其中。如果省略,则模块提供的对象类型和JavaScript资源将安装到全局命名空间中。
一个非限定模块导入的例子如下所示:
import QtQuick 2.0
这个导入允许使用QtQuick模块提供的所有类型,而不需要指定限定符。例如,创建矩形的客户端代码如下所示:
import QtQuick 2.0
Rectangle {
width: 200
height: 100
color: "red"
}
一个符合条件的模块导入示例如下:
import QtQuick 2.0 as Quick
此导入允许同时导入提供冲突类型名称的多个模块,然而,由于导入到限定命名空间的模块所提供的类型的每次使用都必须在限定符之前,这样QML引擎能够明确解决冲突。
下面是一个客户端代码示例,它在使用符合条件的模块导入后创建一个矩形:
import QtQuick 2.0 as Quick
Quick.Rectangle {
width: 200
height: 100
color: "red"
}
有关限定导入的更多信息,请参见即将介绍 导入限定局部命名空间 的部分。
请注意,如果QML文档没有导入提供特定QML对象类型的模块,但试图使用该对象类型,则会发生错误。 这个就像C++里面没有包括头文件就引入了资源。
例如,下面的QML文档没有导入QtQuick,因此尝试使用Rectangle类型将失败:
Rectangle {
width: 200
height: 100
color: "red"
}
在这种情况下,引擎将发出错误并拒绝加载渲染文件。
1. 非模块命名空间的导入
其他类型也可以通过c++中的各种注册函数(如qmlRegisterType())直接注册到命名空间中。以这种方式注册到命名空间中的类型,可以通过导入命名空间来导入,就像该命名空间是模块标识符一样。
这在客户端应用程序中最常见,它们用c++定义自己的QML对象类型,并手动将它们注册到QML类型系统。
2. 导入到限定局部命名空间
import语句可以使用 as 关键字指定将类型导入特定的文档局部命名空间。如果指定了命名空间,那么对导入可用的类型的任何引用都必须以本地命名空间限定符作为前缀。
下面,QtQuick模块被导入命名空间 “CoreItems”。现在,任何对 QtQuick 模块类型的引用都必须以 CoreItems 名称为前缀:
import QtQuick 2.0 as CoreItems
CoreItems.Rectangle {
width: 100; height: 100
CoreItems.Text { text: "Hello, world!" }
// WRONG! No namespace prefix - the Text type won't be found
Text { text: "Hello, world!" }
}
命名空间充当文件范围内模块的标识符。命名空间不会像属性、信号和方法那样,成为根对象的一个可以在外部引用的属性。
如果需要使用两个名称相同但位于不同模块中的QML类型,则命名空间导入很有用。在这种情况下,这两个模块可以导入到不同的命名空间中,以确保代码引用的类型正确:
import QtQuick 2.0 as CoreItems
import "../textwidgets" as MyModule
CoreItems.Rectangle {
width: 100; height: 100
MyModule.Text { text: "Hello from my custom text item!" }
CoreItems.Text { text: "Hello from Qt Quick!" }
}
请注意,可以将多个模块导入到同一个命名空间中,这与将多个模块导入全局命名空间的方式相同。例如:
import QtQuick 2.0 as Project
import QtMultimedia 5.0 as Project
Project.Rectangle {
width: 100; height: 50
Project.Audio {
source: "music.wav"
autoPlay: true
}
}
2. 路径 import
包含QML文档的目录也可以直接导入到QML文档中。这为QML类型提供了一种简单的方法,可以将其分割为可重用的分组:文件系统上的目录。
目录导入的一般形式如下:
import "<DirectoryPath>" [as <Qualifier>]
注意:导入路径是网络透明的:应用程序可以从远程路径导入文档,就像从本地路径导入文档一样简单。请参阅QML文档中有关网络透明性的一般URL解析规则。如果目录是远程的,它必须包含一个目录导入列表qmldir文件,因为如果qmldir文件不存在,QML引擎无法确定远程目录的内容。
<限定符>的语义与模块导入相似,适用于目录导入;有关该主题的更多信息,请参阅前面关于导入到限定局部命名空间的部分。
QML文件的本地目录可以导入,而无需任何额外的设置或配置。也可以导入QML文件的远程目录,但需要存在一个列出qmldir文件的目录。一个本地目录可以有选择地包含一个目录列表qmldir文件,以便定义应该提供给导入该目录的客户端的类型名称,以及指定应该提供给导入者的JavaScript资源。
1. 本地目录导入
本地文件系统上的任何QML文件都可以使用import语句导入本地目录,该语句引用目录的绝对或相对文件系统路径,从而使文件能够使用在该目录中定义的对象类型。
如果本地目录包含一个目录,其中列出了qmldir文件,那么类型将与qmldir文件中指定的类型名称一起可用;否则,它们将使用从QML文档的文件名派生的类型名称。只有以大写字母开头,以’ '结尾的文件名。如果在目录中没有指定qmldir文件,Qml "将作为类型公开。
一个例子
考虑下面的QML项目目录结构。在顶级目录myapp下,在名为mycomponents的子目录中有一组常用UI组件,主应用程序代码在名为main的子目录中,如下所示:
主/应用程序。qml文件可以使用该目录的相对路径导入mycomponents目录,允许它使用该目录中定义的qml对象类型:
import "../mycomponents"
DialogBox {
CheckBox {
// ...
}
Slider {
// ...
}
}
该目录可以导入限定的局部命名空间,在这种情况下,对目录中提供的任何类型的使用都必须限定:
import "../mycomponents" as MyComponents
MyComponents.DialogBox {
// ...
}
导入本地目录的能力对于应用程序中的组件集和应用程序原型之类的情况很方便,尽管任何导入此类模块的代码必须在模块目录移动到另一个位置时更新其相关的导入语句。如果使用QML模块,则可以避免这种情况,因为安装的模块是使用唯一标识符字符串而不是文件系统路径导入的。
2. 远程目录
如果目录中包含一个列出qmldir文件的目录,也可以从远程位置导入QML文件目录。
例如,如果前一个例子中的myapp目录托管在“http://www.my-example-server.com”,并且mycomponents目录包含一个定义如下的qmldir文件:
CheckBox CheckBox.qml
DialogBox DialogBox.qml
Slider Slider.qml
然后,可以使用远程mycomponents目录的URL导入该目录:
import "http://www.my-example-server.com/myapp/mycomponents"
DialogBox {
CheckBox {
// ...
}
Slider {
// ...
}
}
请注意,当一个文件通过网络导入一个目录时,它只能访问该目录中的qmldir文件中指定的QML和JavaScript文件。
警告:当从远程服务器导入目录时,开发人员应该始终注意只加载来自可信源的目录,以避免加载恶意代码。
3. JavaScript资源导入
可以在QML文档中直接导入JavaScript资源。每个JavaScript资源都必须有一个用于访问的标识符。
JavaScript资源导入的一般形式如下:
import "<JavaScriptFile>" as <Identifier>
请注意,在QML文档中必须是唯一的,这与可应用于模块导入的本地命名空间限定符不同。
模块中的JavaScript资源
通过将标识符定义添加到指定模块的qmldir文件中,Javascript文件可以由模块提供。
例如,如果projects.MyQMLProject.MyFunctions模块用下面的qmldir文件指定,并安装到QML导入路径中:
module projects.MyQMLProject.MyFunctions
SystemFunctions 1.0 SystemFunctions.js
UserFunctions 1.0 UserFunctions.js
客户端应用可以通过导入模块并使用与已声明资源相关联的标识符来导入模块中声明的JavaScript资源:
import QtQuick 2.0
import projects.MyQMLProject.MyFunctions 1.0
Item {
Component.onCompleted: { SystemFunctions.cleanUp(); }
}
如果模块被导入到文档局部命名空间中,JavaScript资源标识符必须加上命名空间限定符前缀才能使用:
import QtQuick 2.0
import projects.MyQMLProject.MyFunctions 1.0 as MyFuncs
import org.example.Functions 1.0 as TheirFuncs
Item {
Component.onCompleted: {
MyFuncs.SystemFunctions.cleanUp();
TheirFuncs.SystemFunctions.shutdown();
}
}
有关JavaScript资源的更多信息,请参阅有关在QML中定义JavaScript资源的文档,以及有关如何导入JavaScript资源的更多信息,以及如何从JavaScript资源中使用导入的更多信息,请参阅有关在QML中导入JavaScript资源的深入文档。
三、QML导入路径
当导入一个标识的模块时,QML引擎将在导入路径中搜索匹配的模块。
这个导入路径,由QQmlEngine::importPathList()返回,定义了引擎要搜索的默认位置。默认情况下,这个列表包含:
- 当前文件的目录
- QLibraryInfo::Qml2ImportsPath 指定的位置
- 由 QML2_IMPORT_PATH 环境变量指定的路径
- 资源中的 qrc:/qt-project.org/imports 路径。
可以通过 QQmlEngine::addImportPath() 或 QML2_IMPORT_PATH 环境变量添加其他导入路径。当运行 qmlscene 工具时,你也可以使用-I选项来添加一个导入路径。
四、调试
在查找和加载模块出现问题时,QML_IMPORT_TRACE环境变量可用于调试。
。
设置QML_IMPORT_TRACE环境变量以启用QML导入加载机制的调试输出。
例如,对于这样一个简单的QML文件:
import QtQuick 2.3
Rectangle { width: 100; height: 100 }
如果您在运行 QML Scene 或 QML c++ 应用程序之前设置 QML_IMPORT_TRACE=1,您将看到类似于:
QQmlImportDatabase::addImportPath "/qt-sdk/imports"
QQmlImportDatabase::addImportPath "/qt-sdk/bin/QMLViewer.app/Contents/MacOS"
QQmlImportDatabase::addToImport 0x106237370 "." -1.-1 File as ""
QQmlImportDatabase::addToImport 0x106237370 "Qt" 4.7 Library as ""
QQmlImportDatabase::resolveType "Rectangle" = "QDeclarativeRectangle"