通过QML文档定义对象类型#

QML文档作为可重用类型定义的描述

QML的一个核心特性是通过QML文档以轻量级方式定义QML对象类型,以适应单个QML应用程序的需求。标准的Qt Quick模块提供各种类型,如矩形、文本和图像,用于构建QML应用程序;除此之外,你可以轻松地定义自己的QML类型以便在应用程序中重用。创建自己的类型的能力是任何QML应用程序的基础。

使用QML文件定义对象类型#

自定义QML对象类型的命名#

要创建一个对象类型,应将一个QML文档放入一个名为<TypeName>.qml的文本文件中,其中<TypeName>是类型期望的名称。类型名称有以下要求

  • 它必须由字母数字字符或下划线组成。

  • 它必须以大写字母开头。

然后此文档将自动由引擎识别为QML类型的定义。此外,以这种方式定义的类型将自动对同一本地目录中的其他QML文件提供,因为引擎在解析QML类型名称时_search_立即目录。

注意

QML引擎不自动以这种方式搜索远程目录。如果你的文档通过网络加载,你必须添加一个qmldir文件。参见导入QML文档目录

自定义QML类型定义#

例如,下面是一个声明一个带有子MouseArea的矩形的文档。文档已保存到名为SquareButton.qml的文件中

由于文件名为SquareButton.qml,因此任何同一目录中的其他QML文件都可以作为类型名称使用SquareButton。例如,如果同一目录中有一个myapplication.qml文件,它可以引用SquareButton类型

../_images/documents-definetypes-simple.png

这创建了一个100 x 100的红色矩形,内部有一个MouseArea,正如在SquareButton.qml中定义的那样。当此myapplication.qml文档由引擎加载时,它加载SquareButton.qml文档作为组件并将其实例化以创建一个SquareButton对象。

SquareButton类型封装了在SquareButton.qml中声明的QML对象树。当QML引擎从这个类型中实例化一个SquareButton对象时,它是从SquareButton.qml中声明的矩形对象树实例化一个对象。

注意

在有些文件系统(尤其是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,因为在 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 中的 import 语句特别提供。它可以从一个文件系统上的相对路径导入,也可以作为一个已安装的模块导入;请参阅 模块 获取更多详细信息。

自定义类型的访问属性#

在 .qml 文件中的 root 对象 定义 定义了 QML 类型可用的属性。属于此根对象的全部属性、信号和方法(无论是自定义声明还是来自根对象的 QML 类型)都是外部可访问的,并且可以对此类型的对象进行读取和修改。

例如,上面 SquareButton.qml 文件中的根对象类型是 Rectangle。这意味着可以修改 SquareButton 类型根 Rectangle 对象的定义的任何属性。下面的代码定义了三个具有根 Rectangle 对象属性定制值的 SquareButton 对象

../_images/documents-definetypes-attributes.png

可访问的自定义 QML 类型对象的属性包括任何 自定义属性方法信号。例如,假设 SquareButton.qml 中的 Rectangle 定义如下,增加了属性、方法和信号

任何 SquareButton 对象都可以使用添加到根矩形中的 pressed 属性、buttonClicked 信号和 randomizeColor() 方法。

请注意,任何在 SquareButton.qml 中定义的 id 值都不可访问于 SquareButton 对象,因为 id 值只能在组件声明的组件作用域中访问。上面定义的 SquareButton 对象不能通过 mouseArea 来引用鼠标区域的子项,并且如果它有一个 idroot 而不是 squareButton,则不会与在 SquareButton.qml 中定义的根对象同一值冲突,因为这两个都会在单独的作用域内声明。