网站建设备案,微信小程序做一个多少钱,要做一个网站得怎么做,天津西青区地图QML- 对象属性一、概述二、id 属性三、Property 属性1. 定义属性1. 自定义属性定义中的有效类型2. 为属性属性赋值1. 初始化时的值赋值2. 命令式赋值3. 静态值和绑定表达式值4. 类型安全5. 特殊属性类型1. 对象列表属性2. 分组属性6. 属性别名1. 属性别名的注意事项2. 属性别名…
QML- 对象属性一、概述二、id 属性三、Property 属性1. 定义属性1. 自定义属性定义中的有效类型2. 为属性属性赋值1. 初始化时的值赋值2. 命令式赋值3. 静态值和绑定表达式值4. 类型安全5. 特殊属性类型1. 对象列表属性2. 分组属性6. 属性别名1. 属性别名的注意事项2. 属性别名和类型7. 默认属性8. 只读属性9. 属性修饰符对象四、Signal 属性1. 定义信号属性2. 属性变化信号五、Signal Handler1. 属性更改信号处理程序六、Method 属性1. 定义方法属性2. 附加属性和附加信号处理程序3. 关于访问附加属性和信号处理程序的说明六、Enumeration 属性一、概述
每个QML对象类型都有一组已定义的属性。每个实例都是由一组为该对象类型定义的属性创建的。可以指定几种不同类型的属性其实就是属性就是描述这个对象具体的一些特性QML 引擎就会根据这个对象的属性来绘制界面。
QML文档中的对象声明定义了一个新类型。它还声明了一个对象层次结构当新定义的类型的实例被创建时该对象层次结构将被实例化。 QML object-type属性类型集合如下: id property signal signal handler attributes method attributes attached properties and attached signal handler attributes enumeration attributes
下面就是这些属性的详细说明
二、id 属性
每个QML对象类型都只有一个id属性。此属性由语言本身提供不能由任何QML对象类型重新定义或覆盖。 我们可以为对象实例的id属性赋值以允许其他对象识别和引用该对象。必须以小写字母或下划线开头且不能包含字母、数字和下划线以外的字符。
下面是一个TextInput对象和一个Text对象。TextInput对象的id值设置为myTextInput。通过引用myTextInput.text, Text对象将其Text属性设置为与TextInput的Text属性相同的值。现在两个项目将显示相同的文本:
import QtQuick 2.0Column {width: 200; height: 200TextInput { id: myTextInput; text: Hello World }Text { text: myTextInput.text }
}在声明对象的组件作用域中任何地方都可以通过其id引用对象。因此id值在其组件范围内必须始终是唯一的。有关更多信息请参见作用域和命名解析。 一旦创建对象实例其id属性的值就不能改变。虽然它看起来像一个普通的属性但id属性不是一个普通的属性并且对它应用了特殊的语义;例如无法访问myTextInput。上面例子中的Id。
三、Property 属性
属性是对象的属性它可以被赋予静态值或绑定到动态表达式。属性的值可以被其他对象读取。通常它也可以由另一个对象修改除非特定的QML类型明确禁止对特定属性进行修改。
1. 定义属性
在c中通过注册类的Q_PROPERTY然后将其注册到QML类型系统可以为类型定义属性。或者可以在QML文档的对象声明中定义对象类型的自定义属性语法如下:
[default] property propertyType propertyName通过这种方式对象声明可以将特定值暴露给外部对象或者更容易维护某些内部状态。 属性名必须以小写字母开头且只能包含字母、数字和下划线。JavaScript保留字不是有效的属性名。default关键字是可选的它会修改属性声明的语义。有关默认属性修饰符的更多信息请参见即将介绍的默认属性部分。
声明自定义属性会隐式地为该属性创建一个值改变信号以及调用 PropertyName Changed 时的关联信号处理程序其中 PropertyName 是属性的名称第一个字母大写。
例如下面的对象声明定义了派生自Rectangle基类型的新类型。它有两个新属性并为其中一个属性实现了一个信号处理程序:
Rectangle {property color previousColorproperty color nextColoronNextColorChanged: console.log(The next color will be: nextColor.toString())
}1. 自定义属性定义中的有效类型
除了枚举类型之外任何QML基本类型都可以用作自定义属性类型。例如这些都是有效的属性声明:
Item {property int someNumberproperty string someStringproperty url someUrl
}(枚举值就是整数可以用int类型引用。) 一些基本类型由QtQuick模块提供因此除非导入该模块否则不能用作属性类型。有关更多细节请参阅QML基本类型文档。 注意基本类型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这也适用于自定义QML类型。如果在名为ColorfulButton的文件中定义了QML类型。qml(在客户端导入的目录中)那么ColorfulButton类型的属性也是有效的。
2. 为属性属性赋值
对象实例属性的值可以用两种不同的方式指定。
初始化时的值赋值命令式的赋值
在这两种情况下值可以是静态值也可以是绑定表达式值。
1. 初始化时的值赋值
在初始化时给属性赋值的语法如下:
propertyName : value如果需要初始化值的赋值可以与对象声明中的属性定义结合使用。在这种情况下属性定义的语法如下:
[default] property propertyType propertyName : value下面是属性值初始化的例子:
import QtQuick 2.0Rectangle {color: redproperty color nextColor: blue // combined property declaration and initialization
}2. 命令式赋值
命令式赋值是指在命令式JavaScript代码中将属性的值(静态值或绑定表达式)赋给属性。命令式的赋值语法就是JavaScript的赋值操作符如下所示:
[objectId.]propertyName value下面是命令式赋值的一个例子:
import QtQuick 2.0Rectangle {id: rectComponent.onCompleted: {rect.color red}
}3. 静态值和绑定表达式值
如前所述有两种类型的值可以赋给属性:静态值和绑定表达式值。后者也称为属性绑定。
静态值 不依赖于其他属性的常量值。绑定表达式描述属性与其他属性之间关系的JavaScript表达式。这个表达式中的变量称为属性的依赖项。 QML引擎强化属性与其依赖项之间的关系。当任何依赖项的值发生变化时QML引擎自动重新计算绑定表达式并将新的结果分配给属性。
下面的例子展示了两种值都被赋给属性:
import QtQuick 2.0Rectangle {// both of these are static value assignments on initializationwidth: 400height: 200Rectangle {// both of these are binding expression value assignments on initializationwidth: parent.width / 2height: parent.height}
}注意:要命令式地分配绑定表达式绑定表达式必须包含在传递给Qt.binding()的函数中然后必须将Qt.binding()返回的值分配给属性。相反Qt.binding()在初始化时赋值绑定表达式时不能使用。有关更多信息请参见属性绑定。
4. 类型安全
Properties 是类型安全的。只能为属性指定与属性类型匹配的值。 例如如果一个属性是一个实值而你试图将一个字符串赋值给它就会得到错误:
property int volume: four // generates an error; the propertys object will not be loaded同样如果在运行时为属性分配了错误类型的值则不会分配新值并且会产生错误。 有些属性类型没有自然的值表示对于这些属性类型QML引擎自动执行字符串到类型值的转换。例如即使color类型的属性存储的是颜色而不是字符串你也可以将字符串 “red” 赋值给 color 属性而不会报错。 有关默认支持的属性类型的列表请参阅QML基本类型。此外任何可用的QML对象类型也可以用作属性类型。
5. 特殊属性类型
1. 对象列表属性
可以将QML对象类型值的列表分配给列表类型属性。定义对象列表值的语法是一个用逗号分隔的列表并用方括号括起来:
[ item 1, item 2, ... ]例如Item类型有一个states属性用于保存状态类型对象的列表。下面的代码将这个属性的值初始化为三个状态对象的列表:
import QtQuick 2.0Item {states: [State { name: loading },State { name: running },State { name: stopped }]
}如果列表只包含一个元素可以省略方括号:
import QtQuick 2.0Item {states: State { name: running }
}列表类型属性可以在对象声明中指定语法如下:
[default] property listobjectType propertyName和其他属性声明一样属性初始化也可以和属性声明结合使用语法如下:
[default] property listobjectType propertyName: value下面是一个声明list属性的例子:
import QtQuick 2.0Rectangle {// declaration without initializationproperty listRectangle siblingRects// declaration with initializationproperty listRectangle childRects: [Rectangle { color: red },Rectangle { color: blue}]
}如果您希望声明一个属性来存储一个不一定是QML对象类型值的值列表则应该声明一个var属性。
2. 分组属性
在某些情况下属性包含一组逻辑上的子属性。这些子属性可以使用点表示法或组表示法来指定。 例如Text类型有一个font group属性。下面第一个Text对象使用句点表示法初始化其字体值而第二个使用分组表示法:
Text {//dot notationfont.pixelSize: 12font.b: true
}Text {//group notationfont { pixelSize: 12; b: true }
}分组属性类型是具有子属性的基本类型。其中一些基本类型由QML语言提供而其他类型可能只在导入Qt Quick模块时使用。有关QML基本类型的更多信息请参阅文档。
6. 属性别名
属性别名是持有对另一个属性的引用的属性。普通属性定义为属性分配新的、唯一的存储空间而属性别名将新声明的属性(称为别名属性)连接为对现有属性(别名属性)的直接引用。 属性别名声明看起来与普通属性定义类似不同之处在于它需要alias关键字而不是属性类型而且属性声明的右侧必须是有效的别名引用:
[default] property alias name: alias reference与普通属性不同别名有以下限制。
它只能引用声明别名的类型范围内的对象或对象的属性。它不能包含任意的JavaScript表达式它不能引用在其类型作用域之外声明的对象。别名引用不是可选的这与普通属性的optional默认值不同;在第一次声明别名时必须提供别名引用。它不能引用附加的属性。它不能引用深度大于等于3的层次结构中的属性。下面的代码不起作用:
property alias color: myItem.myRect.border.colorItem {id: myItemproperty Rectangle myRect}不过至多两层深度的属性别名也可以。
property alias color: rectangle.border.colorRectangle {id: rectangle
}例如下面是一个以buttonText为别名的按钮类型它连接到text子元素的text对象:
// Button.qml
import QtQuick 2.0Rectangle {property alias buttonText: textItem.textwidth: 100; height: 30; color: yellowText { id: textItem }
}下面的代码将创建一个按钮并为子text对象定义一个文本字符串:
Button { buttonText: Click Me }在这里修改buttonText会直接修改textItem。文本值;它不会改变其他值然后更新textItem.text。如果buttonText不是别名改变它的值实际上根本不会改变显示的文本因为属性绑定不是双向的:如果textItem是双向的buttonText的值就会改变。文本被改变了但没有反过来。
1. 属性别名的注意事项
只有在组件完全初始化之后才会激活别名。引用未初始化的别名时会产生错误。同样别名属性也会导致错误。
property alias widgetLabel: label//will generate an error
//widgetLabel.text: Initial text//will generate an error
//property alias widgetLabelText: widgetLabel.textComponent.onCompleted: widgetLabel.text Alias completed Initialization然而当在根对象中导入带有属性别名的QML对象类型时该属性会作为常规Qt属性出现因此可以在别名引用中使用。
别名属性可以与现有属性具有相同的名称从而有效地覆盖现有属性。例如下面的QML类型有一个color alias属性其名称与内置的Rectangle::color属性相同:
Rectangle {id: coloredrectangleproperty alias color: bluerectangle.colorcolor: redRectangle {id: bluerectanglecolor: #1234ff}Component.onCompleted: {console.log (coloredrectangle.color) //prints #1234ffsetInternalColor()console.log (coloredrectangle.color) //prints #111111coloredrectangle.color #884646console.log (coloredrectangle.color) //prints #884646}//internal function that has access to internal propertiesfunction setInternalColor() {color #111111}
}任何使用此类型并引用其color属性的对象都将引用别名而不是普通的Rectangle::color属性。但在内部矩形可以正确地设置它的color属性并引用实际定义的属性而不是别名。
2. 属性别名和类型
属性别名不能具有显式类型规范。属性别名的类型是它引用的属性或对象的声明类型。因此如果你通过id引用一个对象并在内联声明了额外的属性那么这些额外的属性将无法通过别名访问:
// MyItem.qml
Item {property alias inner: innerItemItem {id: innerItemproperty int extraProperty}} 不能初始化inner。这个组件外部的extraProperty因为inner只是一个元素:
// main.qml
MyItem {inner.extraProperty: 5 // fails
}但是如果您使用专用的。qml文件将内部对象提取到一个单独的组件中则可以实例化该组件并通过别名提供其所有属性:
// MainItem.qmlItem {// Now you can access inner.extraProperty, as inner is now an ExtraItemproperty alias inner: innerItemExtraItem {id: innerItem}}// ExtraItem.qmlItem {property int extraProperty}7. 默认属性
对象定义可以只有一个默认属性。默认属性是指在另一个对象的定义中声明一个对象而没有声明该对象为某个特定属性的值时赋值给该对象的属性。
用可选关键字default声明属性会将其标记为default属性。例如假设有一个文件MyLabel。带有默认属性someText的qml:
// MyLabel.qmlimport QtQuick 2.0Text {default property var someTexttext: Hello, someText.text}可以在MyLabel对象的定义中指定someText值如下所示:
MyLabel {Text { text: world! }}这与下面代码的效果完全相同:
MyLabel {someText: Text { text: world! }
}不过由于someText属性已经被标记为默认属性因此没有必要显式地将Text对象赋给这个属性。 你会注意到子对象可以添加到任何基于item的类型中而无需显式地添加到children属性中。这是因为Item的默认属性是它的data属性任何为Item添加到这个列表中的项都会自动添加到其子列表中。 默认属性在为子项重新赋值时很有用。请参阅TabWidget示例它使用一个默认属性自动将TabWidget的子组件重新分配为内部ListView的子组件。请参见扩展QML。
8. 只读属性
对象声明可以使用readonly关键字定义只读属性语法如下:
readonly property propertyType propertyName : initialValue只读属性必须在初始化时赋值。在只读属性初始化之后无论通过命令式代码还是其他方式都无法再给它赋值。 例如组件中的代码。下面的onCompleted块是无效的:
Item {readonly property int someNumber: 10Component.onCompleted: someNumber 20 // doesnt work, causes an error}注意:只读属性不能也是默认属性。
9. 属性修饰符对象
属性可以有与其关联的属性值修改器对象。声明与特定属性关联的属性修饰符类型的实例的语法如下:
PropertyModifierTypeName on propertyName {// attributes of the object instance}需要注意的是上面的语法实际上是一个对象声明它将实例化一个作用于预先存在的属性的对象。
某些属性修饰符类型可能只适用于特定的属性类型但语言并没有强制要求这样做。例如QtQuick提供的NumberAnimation类型只会对数值类型(例如int或real)的属性进行动画。使用非数值属性的NumberAnimation不会导致错误但非数值属性不会产生动画。属性修饰符类型与特定属性类型关联时的行为是由其实现定义的。
四、Signal 属性
信号是对象发出的通知表示某些事件发生了:例如属性发生了变化动画开始或停止或者图像下载完毕。例如当用户在鼠标区域内单击时MouseArea类型就会发出单击信号。 无论何时发出特定的信号都可以通过信号处理程序通知对象。信号处理程序使用语法on signal 声明其中 signal 是信号的名称第一个字母大写。信号处理程序必须在发出信号的对象的定义中声明而且处理程序应该包含调用信号处理程序时要执行的JavaScript代码块。 例如下面的onClicked信号处理程序是在MouseArea对象定义中声明的它会在单击MouseArea时被调用从而打印出一条控制台消息:
import QtQuick 2.0Item {width: 100; height: 100MouseArea {anchors.fill: parentonClicked: {console.log(Click!)}}}1. 定义信号属性
在c中可以通过注册类的Q_SIGNAL来为类型定义信号然后将该信号注册到QML类型系统。或者对象类型的自定义信号可以在QML文档的对象声明中定义语法如下:
signal signalName[([type parameter name[, ...]])]试图在同一个类型块中声明两个同名的信号或方法是错误的。但新信号可以重用该类型上现有信号的名称。(这样做时应谨慎因为现有信号可能被隐藏无法访问。) 下面是三个信号声明的例子:
import QtQuick 2.0Item {signal clickedsignal hovered()signal actionPerformed(string action, var actionResult)
}如果信号没有参数“()”括号是可选的。如果使用了参数则必须声明参数类型如上面的actionPerformed信号的string和var参数。允许的参数类型与此页上定义属性属性下列出的参数类型相同。 要发射信号请将其作为方法调用。在信号发出时将调用任何相关的信号处理程序处理程序可以使用定义的信号参数名称来访问相应的参数。
2. 属性变化信号
QML类型还提供内置的属性变化信号每当属性值发生变化时就会发出这种信号如前面在属性属性一节中所述。有关这些信号为什么有用以及如何使用它们的更多信息请参阅即将介绍属性更改信号处理程序的部分。
五、Signal Handler
信号处理程序是一种特殊的方法属性每当发出相关的信号时QML引擎就会调用方法实现。在QML中向对象定义添加信号将自动向对象定义添加关联的信号处理程序该对象定义默认具有空实现。客户端可以提供实现实现程序逻辑。 考虑下面的SquareButton类型其定义在SquareButton中。QML文件如下所示包含激活和停用的信号:
// SquareButton.qmlRectangle {id: rootsignal activated(real xPosition, real yPosition)signal deactivatedproperty int side: 100width: side; height: sideMouseArea {anchors.fill: parentonPressed: root.activated(mouse.x, mouse.y)onReleased: root.deactivated()}}这些信号可以由同一目录中的另一个QML文件中的任何SquareButton对象接收其中信号处理程序的实现由客户端提供:
// myapplication.qmlSquareButton {onActivated: console.log(Activated at xPosition , yPosition)onDeactivated: console.log(Deactivated!)}有关信号使用的更多细节请参阅信号和处理程序事件系统。
1. 属性更改信号处理程序
用于属性更改的信号处理程序采用 property Changed上的语法形式其中 property 是属性的名称第一个字母大写。例如虽然TextInput类型的文档中没有记录textChanged信号但这个信号是隐式可用的因为TextInput有一个text属性所以可以编写一个onTextChanged信号处理程序每当这个属性发生变化时调用:
import QtQuick 2.0TextInput {text: Change this!onTextChanged: console.log(Text has changed to:, text)}六、Method 属性
对象类型的方法是一个函数它可以被调用来执行某些处理或触发进一步的事件。可以将方法连接到信号以便在信号发出时自动调用该方法。有关详细信息请参阅信号和处理程序事件系统。
1. 定义方法属性
在c中通过标记一个类的函数然后用Q_INVOKABLE注册到QML类型系统或者将它注册为类的Q_SLOT可以为一个类型定义方法。另外还可以在QML文档的对象声明中添加自定义方法语法如下:
function functionName([parameterName[, ...]]) { body }QML类型中可以添加方法以便定义独立的、可重用的JavaScript代码块。这些方法既可以在内部调用也可以由外部对象调用。 与信号不同方法的参数类型不必声明因为它们默认为var类型。 试图在同一个类型块中声明两个同名的方法或信号是错误的。不过新方法可以重用该类型上已有方法的名称。(这样做应该谨慎因为现有的方法可能被隐藏变得不可访问。) 下面是一个包含calculateHeight()方法的矩形在指定height值时调用该方法:
import QtQuick 2.0Rectangle {id: rectfunction calculateHeight() {return rect.width / 2;}width: 100height: calculateHeight()}如果方法有参数则可以通过方法内的名称访问参数。下面当单击MouseArea时它会调用moveTo()方法然后该方法可以引用接收到的newX和newY参数来重新定位文本:
import QtQuick 2.0Item {width: 200; height: 200MouseArea {anchors.fill: parentonClicked: label.moveTo(mouse.x, mouse.y)}Text {id: labelfunction moveTo(newX, newY) {label.x newX;label.y newY;}text: Move me!}}2. 附加属性和附加信号处理程序
附加属性和附加信号处理程序是一种机制使对象能够使用对象无法使用的额外属性或信号处理程序进行注释。特别是它们允许对象访问与单个对象特别相关的属性或信号。 QML类型实现可以选择在c中用特定的属性和信号创建附加类型。然后可以在运行时创建此类型的实例并将其附加到特定对象从而允许这些对象访问附加类型的属性和信号。访问这些属性时需要在属性和对应的信号处理程序前添加附加类型的名称。 对附加的属性和处理程序的引用采用以下语法形式:
AttachingType.propertyName
AttachingType.onSignalName例如ListView类型有一个附加属性ListView。isCurrentItem可用于ListView中的每个委托对象。它可以被每个委托对象用来确定它是否是视图中的当前选中项:
import QtQuick 2.0ListView {width: 240; height: 320model: 3delegate: Rectangle {width: 100; height: 30color: ListView.isCurrentItem ? red : yellow}}在这个例子中附加类型的名称是ListView属性是isCurrentItem因此附加属性被称为ListView.isCurrentItem。 附加的信号处理程序也以同样的方式引用。例如组件。onCompleted附加信号处理程序通常用于在组件的创建过程完成时执行一些JavaScript代码。在下面的例子中一旦ListModel被完全创建它的组件。onCompleted信号处理程序将自动被调用以填充模型:
import QtQuick 2.0ListView {width: 240; height: 320model: ListModel {id: listModelComponent.onCompleted: {for (var i 0; i 10; i)listModel.append({Name: Item i})}}delegate: Text { text: index }}由于附加类型的名称是Component并且该类型有一个completed信号因此附加的信号处理程序称为Component. oncompleted。
3. 关于访问附加属性和信号处理程序的说明
一个常见的错误是假定附加的属性和信号处理程序可以从附加这些属性的对象的子对象直接访问。事实并非如此。附加类型的实例只附加到特定的对象上而不附加到对象及其所有子对象上。 例如下面是前面示例涉及附加属性的修改版本。这一次委托是一个项而着色矩形是该项的子元素:
import QtQuick 2.0ListView {width: 240; height: 320model: 3delegate: Item {width: 100; height: 30Rectangle {width: 100; height: 30color: ListView.isCurrentItem ? red : yellow // WRONG! This wont work.}}}这不能按预期工作因为ListView。isCurrentItem只被附加到根委托对象而不是它的子委托对象。由于Rectangle是委托的子元素而不是委托本身因此它无法通过ListView.isCurrentItem访问isCurrentItem附加属性。因此矩形应该通过根委托访问isCurrentItem:
ListView {//....delegate: Item {id: delegateItemwidth: 100; height: 30Rectangle {width: 100; height: 30color: delegateItem.ListView.isCurrentItem ? red : yellow // correct}}}现在delegateItem.ListView.isCurrentItem正确地引用了委托的isCurrentItem属性。
六、Enumeration 属性
枚举提供了一组固定的命名选项。它们可以在QML中使用enum关键字声明:
// MyText.qml
Text {enum TextType {Normal,Heading}
}如上所示枚举类型(例如TextType)和值(例如Normal)必须以大写字母开头。 值通过.引用。值或类型。值。
// MyText.qml
Text {enum TextType {Normal,Heading}property int textType: MyText.TextType.Normalfont.bold: textType MyText.TextType.Headingfont.pixelSize: textType MyText.TextType.Heading ? 24 : 12
}属性int文本类型:MyText.TextType.Normal
字体。粗体:textType MyText.TextType.Heading 字体。pixelSize: textType MyText.TextType.Heading ?24: 12 }
有关QML中枚举用法的更多信息可以在QML基本类型枚举文档中找到。 QML中声明枚举的功能是在Qt 5.10中引入的。