通过 QML 文档定义对象类型

QML 的核心特性之一是它使 QML 对象类型能够通过 QML 文档以轻量级的方式轻松定义,以便在您的应用程序中重复使用。

一、使用 QML 文件定义对象类型

1.1、命名自定义 QML 对象类型

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

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

该文档随后会被引擎自动识别为 QML 类型的定义。此外,在解析 QML 类型名称时,当引擎在直接目录中搜索时,以这种方式定义的类型会自动对同一目录中的其他 QML 文件可用。

1.2、自定义 QML 类型定义

例如,下面的文档声明了一个带有子 MouseArea 的 Rectangle。 该文档已保存到名为 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 文档作为一个组件加载并实例化它以创建一个 SquareButton 对象。

注意:文件名的字母大小写在某些(特别是 UNIX)文件系统上很重要。 建议文件名大小写与所需 QML 类型名称的大小写完全匹配 - 例如,Box.qml 而不是 BoX.qml - 无论 QML 类型将部署到哪个平台。

1.3、内联组件

有时,为一种类型创建一个新文件可能很不方便,例如在多个视图中重用一个小委托时。

如果实际上不需要公开类型,而只需要创建一个实例,则可使用 Component

但是如果想用组件类型声明属性,或者如果想在多个文件中使用它,在这种情况下,可以使用内联组件。 内联组件在文件中声明一个新组件。 语法是:

component <component name> : BaseType {
    // 在这里声明属性和绑定
}

在声明内联组件的文件中,可以简单地通过其名称引用该类型。

// Images.qml
import QtQuick 2.15

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 2.15

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 2.15

Item 
{
    id: root
    property string message: "From A"
    component MyInlineComponent : Item 
    {
        Component.onCompleted: console.log(root.message)
    }
}

// B.qml
import QtQuick 2.15

Item 
{
    A.MyInlineComponent {}
}

注意:内联组件不能嵌套。

二、自定义类型的可访问属性

.qml 文件中的根对象定义定义了可用于 QML 类型的属性。属于这个根对象的所有属性、信号和方法,无论它们是自定义声明的,还是来自根对象的 QML 类型,都可以从外部访问,并且可以为这种类型的对象读取和修改。

例如,上面 SquareButton.qml 文件中的根对象类型是 Rectangle。 这意味着可以为 SquareButton 对象修改由 Rectangle 类型定义的任何属性。

修改自带属性:

// application.qml
import QtQuick 2.0

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

访问自定义属性、方法和信号:

// 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 的 press 属性、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 值只能从声明组件的组件范围内访问。

上一篇:使用ML.NET实现基于RFM模型的客户价值分析


下一篇:QML使用QtWebEngine显示HTML【Echarts】