QtQuick QML 快速上手教程-3 QML 对象属性

 

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

  • id 属性
  • 普通属性
  • 信号属性
  • 信号处理程序属性
  • 方法属性
  • 附加属性和附加信号处理程序属性

这些属性将在下面详细讨论.

id 属性

每种QML对象类型都只有一个属性. 此属性由语言本身提供,并且不能由任何QML对象类型重新定义或覆盖.

可以将值分配给对象实例的属性,以允许该对象被其他对象标识和引用. 此id必须以小写字母或下划线开头,并且不能包含字母,数字和下划线以外的字符.

下面是一个TextInput对象和一个Text对象. TextInput对象的id值设置为" myTextInput". 通过引用myTextInput.text , Text对象将其text属性设置为与TextInputtext属性具有相同的值. 现在,两个项目将显示相同的文本:

import QtQuick 2.0

Column {
    width: 200; height: 200

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

    Text { text: myTextInput.text }
}

可以在声明对象的内的任何位置通过其id引用对象. 因此, id值在其组件范围内必须始终是唯一的. 

创建对象实例后,无法更改其属性的值. 虽然它可能看起来像一个普通的属性,id属性不是一个普通的property属性; 例如,在上面的示例中无法访问myTextInput.id

Property Attributes (普通属性)

属性是可以分配静态值或绑定到动态表达式的对象的属性. 一个属性的值可以被其他对象读取. 通常,它也可以由另一个对象修改,除非特定的QML类型明确禁止特定属性使用.

通过注册类的Q_PROPERTY ,然后再向QML类型系统注册,可以在C ++中为类型定义属性. 或者,可以使用以下语法在QML文档的对象声明中定义对象类型的自定义属性:

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

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

除了枚举类型外,任何QML基本类型都可以用作自定义属性类型,例如

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

此外,任何QML对象类型都可以用作属性类型. 例如:

property Item someItem
property Rectangle someRectangle

为属性属性赋值

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

  • 初始化时
  • 需要的时候赋值

在初始化时为属性分配值的语法是:

<propertyName> : <value>

如果需要,可以将初始化值分配与对象声明中的属性定义组合. 在这种情况下,属性定义的语法变为:

property <propertyType> <propertyName> : <value>

属性值初始化的示例如下:

import QtQuick 2.0

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

需要的时候赋值

import QtQuick 2.0

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

以下示例,显示了两种方法给属性赋值:

import QtQuick 2.0

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

属性安全问题

就像c++一样,int 类型不能赋值string,QML里也一样只能为属性分配与属性类型匹配的值

例如,如果一个属性是一个实数,并且如果您尝试为其分配一个字符串,则会出现错误:

property int volume: "four"  // generates an error; the property's object will not be loaded

同样,如果在运行时为属性分配了错误类型的值,则不会分配新值,并且会生成错误.

可以为列表类型属性分配QML对象类型值的列表. 定义对象列表值的语法是用方括号括起来的逗号分隔列表:

例如, Item类型具有一个states属性,该属性用于保存State类型对象的列表. 下面的代码将该属性的值初始化为三个State对象的列表:

import QtQuick 2.0

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

如果列表包含单个项目,则可以省略方括号:

import QtQuick 2.0

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

可以使用以下语法在对象声明中指定列表类型属性:

property list<<objectType>> propertyName

//或者
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属性.

 

Signal Attributes  信号属性

信号是来自某个对象的通知,表明发生了某些事件:例如,属性已更改,动画已开始或停止或下载图像时. 例如, MouseArea类型具有单击信号,当用户在鼠标区域内单击时发出该信号.

每当发出特定信号时,可以通过信号处理程序通知对象. where is the name of the signal, with the first letter capitalized. 使用语法声明信号处理程序,其中是名称,首字母大写. 必须在发出信号的对象的定义内声明信号处理程序,并且该处理程序应包含在调用信号处理程序时要执行的JavaScript代码块.

例如,下面的信号处理程序在MouseArea对象定义中声明,并在单击MouseArea时被调用,从而导致控制台消息被打印:

import QtQuick 2.0

Item {
    width: 100; height: 100

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

通过注册一个类的Q_SIGNAL ,然后在QML类型系统中注册,可以为C ++中的类型定义一个信号. 或者,可以使用以下语法在QML文档的对象声明中定义对象类型的自定义信号:

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

试图在同一类型块中声明两个具有相同名称的信号或方法是错误的. 但是,新信号可能会在类型上重复使用现有信号的名称. (这应该谨慎行事,因为现有信号可能会被隐藏并变得难以访问.)

这是信号声明的三个示例:

import QtQuick 2.0

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

如果信号没有参数,则"()"括号是可选的. 如果使用了参数,则必须声明参数类型,就像上述actionPerformed信号的stringvar参数一样. 允许的参数类型与此页面上的" 定义属性属性"下列出的参数类型相同.

要发出信号,请将其作为方法调用. 发出信号时,将调用任何相关的信号处理程序 ,并且处理程序可以使用定义的信号参数名称来访问相应的参数.

 

属性改变信号

QML类型还提供了内置的 ,每当属性值更改时都会发出该 ,如先前在属性属性部分中所述. QML属性的值更改时,会自动发出信号.格式是on<Signal> 这种形式。

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onPressedChanged: {
            console.log("Mouse area is pressed?", pressed)
        }
    }
}

在上面示例中MouseArea触发pressedChanged信号。我们捕捉这个信号就用onPressedChanged就可以了 ,没错,首部加on,信号首字母变为大写就可以了!

即使MouseArea文档没有记录名为onPressedChanged的信号处理程序,该信号onPressedChangedpressed属性存在的事实隐式提供.

Using the Connections Type

在某些情况下,可能希望访问发出该信号的对象之外的信号. 为此, QtQuick模块提供了Connections类型,用于连接到任意对象的信号. Connections对象可以从其指定的目标接收任何信号.

例如, onClicked在前面的示例中的处理程序可能已被由所述根接收矩形代替,通过将onClicked处理程序在一个连接对象,该对象具有其目标设定到鼠标区域 :

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Connections {
        target: mouseArea
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

简单的介绍下qml信号,会具体一章来讲qml的信号和槽,并且会有详细的示例代码。还有c++与qml的信号传递与一些好用的技巧分享。

 

Attributes 方法属性

可以通过在C ++中为类型定义一种方法,方法是标记一个类的功能,然后用Q_INVOKABLE在QML类型系统中注册该类,或者将其注册为该类的Q_SLOT . 或者,可以使用以下语法将自定义方法添加到QML文档中的对象声明中:

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

可以将方法添加到QML类型,以定义独立的可重用的JavaScript代码块. 这些方法可以在内部或外部对象中调用.

与信号不同,方法参数类型不必声明,因为它们默认为var类型.

下面是一个带有calculateHeight()方法的矩形 ,该矩形在分配height值时被调用:

import QtQuick 2.0
Rectangle {
    id: rect

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

    width: 100
    height: calculateHeight()
}

如果该方法具有参数,则可以在方法内按名称访问它们. 在下面,当单击MouseArea时,它将调用moveTo()方法,该方法然后可以引用接收到的newXnewY参数来重新newY文本:

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!"
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章