通过 QML 文档定义对象类型
QML 的核心特点之一是,它能通过 QML 文档以轻量级方式轻松定义 QML 对象类型,以满足个别 QML 应用程序的需要。标准 Qt Quick模块为构建 QML 应用程序提供了各种类型,如Rectangle 、Text 和Image ;除此之外,您还可以轻松定义自己的 QML 类型,以便在您的应用程序中重复使用。这种创建自己类型的能力构成了任何 QML 应用程序的基石。
用 QML 文件定义对象类型
命名自定义 QML 对象类型
要创建对象类型,应将 QML 文档放入名为<TypeName>.qml的文本文件中,其中<TypeName>是所需的类型名称。类型名称有以下要求:
- 必须由字母数字字符或下划线组成。
- 必须以大写字母开头。
然后,引擎会自动把这个文档识别为 QML 类型定义。此外,以这种方式定义的类型会自动提供给同一本地目录下的其它 QML 文件,因为引擎在解析 QML 类型名称时,会在直接目录下搜索。
注意: QML 引擎不会自动搜索远程目录。如果你的文档是通过网络加载的,你必须添加一个 qmldir 文件。请参阅导入 QML 文档目录。
自定义 QML 类型定义
例如,下面是一个文档,它声明了一个Rectangle 和一个子MouseArea 。文档已保存到名为SquareButton.qml
的文件中:
// SquareButton.qml import QtQuick 2.0 Rectangle { property int side: 100 width: side; height: side color: "red" MouseArea { anchors.fill: parent onClicked: console.log("Button clicked!") } }
由于文件名是SquareButton.qml
,现在同一目录下的任何其他 QML 文件都可把它用作名为SquareButton
的类型。例如,如果同一目录中有myapplication.qml
文件,它就可以引用SquareButton
类型:
// myapplication.qml import QtQuick 2.0 SquareButton {}
这样就创建了一个 100 x 100 的红色Rectangle ,内含MouseArea ,如SquareButton.qml
所定义。引擎加载该myapplication.qml
文档时,会将 SquareButton.qml 文档作为组件加载,并将其实例化以创建SquareButton
对象。
SquareButton
类型封装了SquareButton.qml
中声明的 QML 对象树。当 QML 引擎从该类型实例化SquareButton
对象时,它就从SquareButton.qml
声明的Rectangle 树中实例化了一个对象。
注意: 在某些(特别是 UNIX)文件系统中,文件名的字母大小写很重要。建议文件名的大小写与所需 QML 类型名的大小写完全一致,例如,Box.qml
,而不是BoX.qml
,无论 QML 类型将部署到哪个平台。
内联组件
有时,为一个类型创建一个新文件会很不方便,例如在多个视图中重复使用一个小的委托时。如果你实际上不需要公开类型,而只需要创建一个实例,Component 是一个选择。但如果你想用组件类型声明属性,或者想在多个文件中使用它,Component
就不是一个选项了。在这种情况下,你可以使用内联组件。内联组件是在文件中声明一个新组件。语法如下
component <component name> : BaseType { // declare properties and bindings here }
在声明内联组件的文件中,只需使用其名称即可引用该类型。
// Images.qml import QtQuick Item { component LabeledImage: Column { property alias source: image.source property alias caption: text.text Image { id: image width: 50 height: 50 } Text { id: text font.bold: true } } Row { LabeledImage { id: before source: "before.png" caption: "Before" } LabeledImage { id: after source: "after.png" caption: "After" } } property LabeledImage selectedImage: before }
而在其他文件中,则必须以包含组件的名称为前缀。
// LabeledImageBox.qml import QtQuick Rectangle { property alias caption: image.caption property alias source: image.source border.width: 2 border.color: "black" Images.LabeledImage { id: image } }
注意: 内联组件不与它们所声明的组件共享作用域。在下面的示例中,当创建文件 B.qml 中的A.MyInlineComponent
时,将出现 ReferenceError,因为root
在 B.qml 中并不作为 id 存在。因此,建议不要在内联组件中引用不属于该组件的对象。
// A.qml import QtQuick Item { id: root property string message: "From A" component MyInlineComponent : Item { Component.onCompleted: console.log(root.message) } } // B.qml import QtQuick Item { A.MyInlineComponent {} }
注意: 内联组件不能嵌套。
导入当前目录外定义的类型
如果SquareButton.qml
与myapplication.qml
不在同一目录下,则SquareButton
类型需要通过myapplication.qml
中的导入语句才能使用。它可以从文件系统的相对路径导入,也可以作为已安装的模块导入;详情请参阅模块。
自定义类型的可访问属性
.qml 文件中的根对象定义定义了 QML 类型的可用属性。属于该根对象的所有属性、信号和方法--无论它们是自定义声明的,还是来自根对象的 QML 类型--都是可从外部访问的,可为该类型的对象读取和修改。
例如,上述SquareButton.qml
文件中的根对象类型是Rectangle 。这意味着Rectangle 类型定义的任何属性都可以为SquareButton
对象修改。下面的代码定义了三个SquareButton
对象,并为SquareButton
类型的根Rectangle 对象的某些属性自定义了值:
// application.qml import QtQuick 2.0 Column { SquareButton { side: 50 } SquareButton { x: 50; color: "blue" } SquareButton { radius: 10 } }
自定义 QML 类型对象可访问的属性包括为对象额外定义的任何自定义属性、方法和信号。例如,假设SquareButton.qml
中的Rectangle 定义如下,并增加了属性、方法和信号:
// SquareButton.qml import QtQuick 2.0 Rectangle { id: root property bool pressed: mouseArea.pressed signal buttonClicked(real xPos, real yPos) function randomizeColor() { root.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1) } property int side: 100 width: side; height: side color: "red" MouseArea { id: mouseArea anchors.fill: parent onClicked: (mouse)=> root.buttonClicked(mouse.x, mouse.y) } }
任何SquareButton
对象都可以使用已添加到根Rectangle 的pressed
属性、buttonClicked
信号和randomizeColor()
方法:
// application.qml import QtQuick 2.0 SquareButton { id: squareButton onButtonClicked: (xPos, yPos)=> { console.log("Clicked", xPos, yPos) randomizeColor() } Text { text: squareButton.pressed ? "Down" : "Up" } }
请注意,SquareButton.qml
中定义的任何id
值都不能被SquareButton
对象访问,因为 id 值只能在声明组件的组件范围内访问。上面的SquareButton
对象定义不能为了引用MouseArea 子对象而引用mouseArea
,如果它的id
是root
而不是squareButton
,就不会与SquareButton.qml
中定义的根对象的相同值id
冲突,因为两者是在不同的作用域中声明的。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.