通过 QML 文档定义对象类型

QML 的核心特性之一是它可以通过 QML 文档轻量级地定义 QML 对象类型,以满足单个 QML 应用程序的需求。标准的 Qt Quick 模块提供了如 RectangleTextImage 等多种类型,用于构建 QML 应用程序;除此之外,你可以轻松地定义自己的 QML 类型以便在应用程序中复用。创建自定义类型的这种能力是任何 QML 应用程序的基础。

使用 QML 文件定义对象类型

自定义 QML 对象类型的命名

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

  • 必须由字母数字字符或下划线组成。
  • 必须以大写字母开头。

此文档随后将被引擎自动识别为 QML 类型的定义。此外,这种方式的定义将自动提供给同一本地目录中的其他 QML 文件,因为引擎在解析 QML 类型名称时会在直接目录中搜索。

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

自定义 QML 类型定义

例如,以下是一个声明了带有子 MouseAreaRectangle 的文档。该文档已保存为名为 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类型部署到哪个平台。

内联组件

有时,为类型创建新文件可能不方便,例如在多个视图中重复使用一个小型代理时。如果您不需要公开类型,而只需创建一个实例,可以使用<(bit translate="no">Component),但是如果您想声明组件类型属性,或者想在多个文件中使用它,则不可使用Component。在这种情况下,您可以使用<生活中的组件Maker。内联组件在文件内部声明了新的组件。其语法如下

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为root的对象。因此,建议不要在内联组件中引用不属于它的对象。

// 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中特别提供的语句将SquareButton类型公开。它可以从文件系统上的相对路径导入,或作为已安装的模块导入;有关更多详细信息,请参阅模块

自定义类型的可访问属性

.qml文件中的定义定义了可用的QML类型的属性。所有属于此root对象的所有属性、信号和方法都可以从外部访问,并且可以读取和修改该类型的对象。

例如,上述SquareButton.qml文件中的root对象类型是Rectangle。这意味着可以修改属于Rectangle类型的任何属性,并定义以下三个带有自定义值的SquareButton对象

// application.qml
import QtQuick 2.0

Column {
    SquareButton { side: 50 }
    SquareButton { x: 50; color: "blue" }
    SquareButton { radius: 10 }
}

自定义QML类型的对象可访问的属性包括任何已定义的自定义属性方法信号。例如,假设RectangleSquareButton.qml中已按如下方式定义,并添加了额外的属性、方法和信号

// 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对象都可以使用添加到rootRectanglepressed属性、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 子项,并且如果它有一个而非 squareButtonidroot,则不会与在 SquareButton.qml 中定义的根对象的相同值 id 冲突,因为这两个是在不同的作用域中声明的。

© 2024 Qt公司。此处包含的文档贡献是各自所有者的版权。提供的文档受GNU自由文档许可证版本1.3的条款约束,由自由软件基金会发布。Qt及其相关标志是芬兰以及/或其他国家Qt公司的商标。所有其他商标均为各自所有者的财产。