本页内容

通过 QML 文档定义对象类型

QML 的核心特性之一在于,它能够通过 QML 文档以轻量级的方式轻松定义 QML 对象类型,以满足各个 QML 应用程序的需求。标准 Qt Quick 模块提供了Rectangle 、Text 和Image 等各种类型,用于构建QML应用程序;除此之外,您还可以轻松定义自己的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 {}

myapplication.qml 中的方形按钮类型继承了 SquareButton.qml 中定义的属性。

这将创建一个 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 不在同一目录下,则需要在myapplication.qml 中通过import语句显式导出SquareButton 类型。该类型既可以从文件系统上的相对路径导入,也可以作为已安装的模块导入;更多详情请参阅模块章节。

自定义类型的可用属性

.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 (其值为相同)产生冲突,因为二者是在不同的作用域内声明的。

© 2026 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.