QML属性

本文详细介绍了QML中的属性系统,包括ID属性、属性特性、定义属性、属性赋值、特殊属性类型等。重点讲解了ID属性的唯一性、属性的读写权限、属性别名的使用限制以及如何定义和使用信号属性。同时,还探讨了方法属性、附加属性和枚举属性等概念,为深入理解QML编程提供了基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 类型名称必须以大写字母开头

导入语法

一个QML文档可以在文件顶部具有一个或多个导入。导入可以是以下任意一项:

  • 已注册类型的版本化名称空间(例如,通过插件)
  • 在相对目录中包含qml类型定义的文件
  • 一个JavaScript文件

各种import的通用形式如下:

  • import Namespace VersionMajor.VersionMinor
  • import Namespace VersionMajor.VersionMinor as SingletonTypeIdentifier
  • import "directory"
  • import "file.js" as ScriptIdentifier

例子:

import QtQuick 2.0
import QtQuick.LocalStorage 2.0 as Database
import "../privateComponents"
import "somefile.js" as Script

QML对象属性

QML对象类型属性类型集如下:

  • the id attribute
  • property attributes
  • signal attributes
  • signal handler attributes
  • method attributes
  • attached properties and attached signal handler attributes
  • enumeration attributes

 

ID属性(特殊属性)

每种QML对象类型都只有一个id属性。此属性由语言本身提供,

id值必须以小写字母或下划线开头,并且不能包含字母,数字和下划线以外的字符。

id必须唯一

id定义后不能通过属性赋值进行修改

import QtQuick 2.0

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

 

属性的特性

一个属性的值可以被其他对象读取。通常,它也可以由另一个对象修改,除非特定的QML类型明确禁止特定属性使用。、

定义属性的特性

在C++中使用Q_PROPERTY进行定义后,会注册到QML类型系统中,还可以在QML文档中使用

[default] property <propertyType> <propertyName>

进行注册。这样,就可以属性值暴露给外部对象。

属性名称必须以小写字母开头,并且只能包含字母,数字和下划线。JavaScript保留字不是有效的属性名称。

声明自定义属性会隐式创建该属性的值更改信号以及名为on <PropertyName> Changed的关联信号处理程序,其中<PropertyName>属性的名称,首字母大写。

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}

枚举类型外,任何QML基本类型都可用作自定义属性类型。

Item {
    property int someNumber
    property string someString
    property url someUrl
}

QtQuick模块提供了一些基本类型,因此除非导入模块,否则不能用作属性类型。

var基本类型是通用占位符类型,可以保存任何类型的值,包括列表和对象:

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

此外,任何QML对象类型(包括自定义类型)都可以用作属性类型。例如

property Item someItem
property Rectangle someRectangle

属性赋值

可以通过两种方式指定对象实例的属性值

  • a value assignment on initialization (初始化)
  • an imperative value assignment (命令行赋值)

初始化赋值方法

<propertyName> : <value>

定义属性时顺带赋值

[default] property <propertyType> <propertyName> : <value>

赋值示例

import QtQuick 2.0

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}

命令行赋值,是使用javascript中进行赋值

[<objectId>.]<propertyName> = value

示例

import QtQuick 2.0

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

类型安全

属性是类型安全的。只能为属性分配与属性类型匹配的值

特殊属性类型

Object List Property Attributes

列表类型定义

    [ <item 1>, <item 2>, ... ]

例:

import QtQuick 2.0

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

如果列表中只有一项,可以省略方括号

import QtQuick 2.0

Item {
    states: State { name: "running" }
}

列表属性声明语法:

[default] property list<<objectType>> propertyName

 

声明加初始化语法
 

[default] property list<<objectType>> propertyName: <value>

例子

import QtQuick 2.0

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

如果声明一个值不是QML对象,需要使用var定义

 

分组属性

在某些情况下,属性包含一组逻辑的子属性属性。可以使用点符号(.)或组符号({})将这些子属性属性分配给它们。

例 

Text {
    //dot notation
    font.pixelSize: 12
    font.b: true
}

Text {
    //group notation
    font { pixelSize: 12; b: true }
}

属性别名

 

属性别名语法

[default] property alias <name>: <alias reference>

命名用限制:

1.只能引用在同一作用域的对象或对象属性

2.不能包含Js表达式

3.属性别名必须初始化

4.不能引用附加属性

5.不能引用深度为3或更大的层次结构内的属性

例 

property alias color: myItem.myRect.border.color  //超过3层,不能使用

Item {
    id: myItem
    property Rectangle myRect
}
property alias color: rectangle.border.color  //命名用两级是可以的

Rectangle {
    id: rectangle
}

// Button.qml
import QtQuick 2.0

Rectangle {
    property alias buttonText: textItem.text  //按钮就可以直接操作文本了

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

使用按钮如下:

Button { buttonText: "Click Me" }

属性别名注意事项

仅在组件完全初始化后才能激活别名

别名属性可能与现有属性具有相同的名称,从而有效覆盖现有属性。

例:

Rectangle {
    id: coloredrectangle
    property alias color: bluerectangle.color
    color: "red"

    Rectangle {
        id: bluerectangle
        color: "#1234ff"
    }

    Component.onCompleted: {
        console.log (coloredrectangle.color)    //prints "#1234ff"
        setInternalColor()
        console.log (coloredrectangle.color)    //prints "#111111"
        coloredrectangle.color = "#884646"
        console.log (coloredrectangle.color)    //prints #884646
    }

    //internal function that has access to internal properties
    function setInternalColor() {
        color = "#111111"
    }
}

属性别名没有明确的类型,如果将为一个对象的ID指定别明,是不能使用别名掉用对象属性的

例 

// MyItem.qml
Item {
    property alias inner: innerItem

    Item {
        id: innerItem
        property int extraProperty
    }
}


// main.qml
MyItem {
    inner.extraProperty: 5 // fails
}

如果别名组件是一个单独文件定义的对象的话,是可以使用别名访问属性的

// MainItem.qml
Item {
    // Now you can access inner.extraProperty, as inner is now an ExtraItem
    property alias inner: innerItem

    ExtraItem {
        id: innerItem
    }
}

// ExtraItem.qml
Item {
    property int extraProperty
}

默认属性

定义默认属性的语法

  default property var someText

默认属性每个对象只能定义一个

默认对象不用再通过属性名进行赋值

// MyLabel.qml
import QtQuick 2.0

MyLabel {
    default property var someText

    text: "Hello, " + someText.text
}


//调用时没有使用someText:Text { text: "world!" },默认属性可省略someText:
MyLabel {
    Text{ text: "world!" }
}




只读属性

只读属性语法:

readonly property <propertyType> <propertyName> : <initialValue>

初始化时必须为只读属性分配一个值。以后再也不能以任何方式进行赋值。

属性修改器对象

属性可以有属性值修改器对象和他们关联。声明关联到具体属性的修改器类型实例的语法如下:

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

信号属性

信号处理程序使用 on<Signal> 语法声明, <Signal> 是信号名,第一个字母大写。信号处理程序必须声明在触发该信号的对象的定义内,并且处理程序应该包含 JavaScript 代码块当信号处理程序被调用时执行。

import QtQuick 2.0

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

定义信号属性

signal <signalName>[([<type> <parameter name>[, ...]])]

import QtQuick 2.0

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(string action, var actionResult)
}

触发信号,像调用方法一样调用信号。信号被触发时任何信号相关的处理将被调用,处理程序可以使用信号已定义的参数访问各自的参数。

信号处理程序属性

// SquareButton.qml
Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)  //定义信号
    signal deactivated  //定义信号

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onPressed: root.activated(mouse.x, mouse.y)  //发送信号
        onReleased: root.deactivated() //发送信号
    }
}


// myapplication.qml  //同一文件夹下接收信号并处理。
SquareButton {
    onActivated: console.log("Activated at " + xPosition + "," + yPosition)
    onDeactivated: console.log("Deactivated!")
}

属性改变信号的处理

属性改变的信号的处理程序使用语法 on<Property>Changed ,<Property> 是属性的名字并且第一个字母大写。

import QtQuick 2.0

TextInput {
    text: "Change this!"

    onTextChanged: console.log("Text has changed to:", text)
}

方法属性

对象类型的方法是一个可以被调用去执行一些处理或触发后续事件的函数。方法可以连接到信号以便信号被触发时它可以被自动调用。

定义方法属性

类型的方法定义,可以在C++中使用 Q_INVOKABLE 标注将被注册到QML类型系统的类的函数,或者注册该函数为类的 Q_SLOT 。使用如下的语法在QML文档内添加自定义方法到对象的声明:

function <functionName>([<parameterName>[, ...]]) { <body> }

方法定义:

import QtQuick 2.0
Rectangle {
    id: rect

    function calculateHeight() {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

方法使用:

import QtQuick 2.0

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX, newY) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

附加属性和附加信号处理程序

附加属性和附加信号处理程序是一种使对象被解释为扩展属性或信号处理程序(否则无效)的机制,特别地,这允许对象访问与个别对象明确相关的属性或者信号。

语法:

<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>

示例

/*比如, ListView 类型有一个可被附加的属性 ListView.isCurrentItem 并且 ListView 内的每一个代理对象可使用(此附加属性)。这可以被每一个不同的代理对象用来确定自己是否是视图内当前被选中的元素。*/
import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

访问附加属性和信号处理程序的注意事项

附加类型的实例仅仅附属于特定对象,不属于对象和它的所有子对象。

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow"    // WRONG! This won't work.
        }
    }
}


//以下是正确写法

ListView {
    //....
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow"   // correct
        }
    }
}

 

枚举属性

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}



// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType == MyText.TextType.Heading
    font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12
}

枚举属性只能在5.10以后使用

 

https://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值