通过 QML 文档定义对象类型

QML 的核心特点之一是,它能通过 QML 文档以轻量级方式轻松定义 QML 对象类型,以满足个别 QML 应用程序的需要。标准 Qt Quick模块为构建 QML 应用程序提供了各种类型,如RectangleTextImage ;除此之外,您还可以轻松定义自己的 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.qmlmyapplication.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 对象都可以使用已添加到根Rectanglepressed 属性、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 ,如果它的idroot 而不是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.