QtQuick-QML类型系统-对象特性(id和属性)

每一个QML对象类型都包含一组定义好的特性。

每个对象类型的实例在创建时都会包含一组特性,这些特性是在该对象类型中定义的。一个QML文档中的对象声明定义了一个新的类型,其中可以包含如下特性:

  1. id特性
  2. 属性(property)特性
  3. 信号(signal)特性
  4. 信号处理器(signal handler)特性
  5. 方法(method)特性
  6. 附加属性(attahed properties)和附加信号处理器(attached signal handler)特性
  7. 枚举(enumeration)特性

下面将介绍它们,也可以在Qt帮助中通过QML QObject Attributes关键字查看。

一、id特性

每个对象可以指定一个唯一的id,可以在其他对象中识别并引用该对象。

这个特性是语言本身提供的,不能被QML对象类型进行重定义或重写。

可以在一个对象所在组件中的任何位置使用该对象的id来引用这个对象。因此id值在一个组件的作用域中必须是唯一的。

下面通过id来设置第2个Text拥有与第一个Text一样的text属性值:

Row{Text{id: text1text: "Hello World"}Text{ text: text1.text}
}

id必须使用小写字母或者下划线开头,且由字母、数字、下划线组成。

二、属性特性

可以分配静态的属性,也可以分配绑定一个动态表达式。

属性的值可以被其他对象获取。一般而言,属性的值也可以被其他对象修改,除非显示声明不允许这么做(声明为只读属性)。

1. 声明属性特性

属性可以在C++中通过线先注册一个类的Q_PROPERTY宏,再注册到QML类型系统中进行创建。

此外,还可以在QML文档中使用下面的语法声明一个属性:

[default] [required] [readonly] property <propertyType> <propertyName>

使用这种机制可以很容易地将属性值暴露给外部对象或维护对象的内部状态。

与id类似,属性的名字propertyName也必须以小写字母开始,可以包含字母、数字和下划线。另外JavaScript不能作为属性的名字。前面的修饰符是可选的。

  • default:默认属性
  • required:必须属性
  • readonly:只读属性

声明一个自定义的属性,则会隐式地为该属性创建一个值改变信号以及一个相应的信号处理器on<PropertyName>Changed。其中<PropertyName>是自定义属性的名字,首字母大写。

例如:

import QtQuickRectangle {property color previousColor;property color nextColor;onNextColorChanged:console.log("The next color will be: " + nextColor.toString());nextColor:"red"width:400; height:300; color: nextColorMouseArea {anchors.fill: parentonClicked: nextColor = "yellow"}
}

这个例子中,从Rectangle基类型派生了一个新类型,它包含两个新属性:previousColornextColor
我们希望在nextColor属性发生改变时得到通知,所有增加了一个信号处理器onNextColroChanged来达到目的。

除了enumeration外,QML的基本类型都可以用作自定义属性的类型。

例如,下面的声明都是正确的:

Item{property int someNumberproperty string someStringproperty url someUrl
}

由于enumeration其实就是整型int,所有当需要enumeration的时候,可以选择用int类型替代。

对于QML的其他基本类型,只要导入相应模块,也可以作为属性类型。需要注意的是var类型:var是一种通用的占位符类型,类似于QVariant,它可以包含任意类型的值,包括列表和对象。
例如:

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内置的对象类型,还可以将自定义的对象类型作为属性类型使用。

2. 初始化和赋值

qml属性的值可以通过初始化或者赋值操作来给出,这两种途径都可以直接给定一个静态数据值或一个表达式。

2.1 初始化

属性可以在初始化时直接赋值:

<propertyName> : <value>

也可以将属性声明和属性初始化结合成一条语句:

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

下面看一个例子:

  • color属性使用了初始化语句;
  • nextColor则将属性声明与属性初始化结合在一起。
import QtQuickRectangle{color: "yellow"property color nextCOlor: "blue"
}
2.2 代码中赋值

赋值操作与JavaScript相同,使用赋值运算符(=)完成。其语法是:

[<objectId>.]<propertyName> = value

例子(将rect.colr的值赋成red):

import QtQuickRectangle{id: rootComponent.onCompleted:{rect.color = "red}
}
2.3 有效的属性值

一个属性可以分配两种类型的值:

  1. 静态值
    • 与属性要求的类型相匹配(或者可以转换成属性要求的类型)的值。
  2. 绑定表达式的值
    • 该JavaScript表达式可以运算出结果,并且运算结果的类型与属性要求的类型相匹配(或者可以转换成属性要求的类型)。
    • 当绑定表达式的值发生变化时,表达式可以自动更新运算结果。

例子:

import QtQuick
Rectangle{//静态值初始化width: 400height: 200color: "red"Rectangle{//使用绑定表达式初始化width: parent.width/2height: parent.height}
}
2.4 类型安全

前面已经强调,QML属性的初始化或赋值时,类型必须匹配或能够转换成匹配的类型。但是,上面的代码却将字符串"red"赋值给了color类型的属性。

这是因为QML提供了一系列转换器,能够将string转换成很多其他的属性类型。正因为有这些转换器的存在,才可以将"red"转换成颜色类型。由此可以看出,QML属性是类型安全的,属性值的类型必须与属性要求的类型相匹配。

3. 对象列表属性

可以将一个QML类型值列表赋值给一个列表类型的属性,其语法如下所示:

[<item>, <item2>, ...]

列表被包含在一对方括号中,使用都好分割列表中的对象。

例如,Item类型有一个states属性,用于保存一个State类型对象的列表。下面的代码片段给出如何初始化这个states属性:

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

如果列表仅包含一个对象,也可以省略方括号:

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

可以使用下面的语法在对象声明时指定一个列表类型属性:

[default] property list<<objectType>> propertyName

而且与其他属性声明类似,在属性声明时也可以使用下面的语法进行属性初始化:

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

例子:

Rectangle {//只声明,不初始化property list<Rectangle> siblingRects//声明并且初始化property list<Rectangle> childRects: [Rectangle {color: "red"},Rectangle {color: "blue"}]width: 400; height: 300; color: childRects[1].colorMouseArea{anchors.fill: parentonClicked:{for(var i=0;i<childRects.length; ++i){console.log("color", i, childRects[i].color);}}}
}

说明一下:可以使用length属性来获取列表中对象数量,可以通过[]index语法来获取列表中的指定值。如果要声明一个用来存储一列值的属性,而不是使用QML对象类型的值,那么可以使用var属性。

4. 属性组

QML属性可以按照逻辑关系进行分组。属性可以是一个包含子属性特性的逻辑组,而子属性特性也可以使用点标记或者组标记来赋值。例如,Text类型的font属性是一个属性组。

代码示例(第一个Text使用点标记初始化font值,第二个则使用组标记的形式):

Row {Text {//点标记font.pixelSize: 12; font.bold: truetext: "text1"}Text {//组标记font: {pixelSize:12; bold: true}text: "text2"}
}

5. 属性别名

属性别名类似C++的引用。与普通的属性声明不同,属性别名不需要分配一个新的唯一的存储空间,而是将新声明的属性(称为别名属性,the aliasing property)作为一个已经存在的属性(称为被别名的属性,the aliased property)的直接引用。

我们可以给属性定义一个别名,以后就可以利用这个别名操作这个属性。属性别名的声明与属性的声明类似,但是需要使用alias关键字代替属性类型,而且在属性声明的右侧必须是一个有效的别用引用。
语法:

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

与普通属性不同,别名只能引用到其声明处的类型作用域中的一个对象或一个对象的属性。它不能包含任何JavaScript表达式,也不能引用类型作用域之外的对象。

还要注意右侧的alias reference不是可选的,这与普通属性性声明中可选的默认值不同。

而且当第一次声明别名时alias reference必须提供,这一点与C++引用也非常相似。
例子:

//Button.qml
import QtQuick
Rectangle{property alias buttonText: textItem.textwidth: 100; height: 30; color: "yellow"Text: {id: textItem}
}

这里定义了一个Button类型。Button有一个buttonText的属性别名,指向其Text子对象的text属性。在其他QML文档文档中使用Button类型时,可以之际使用如下语句定义其Text子对象的文本:

Button {buttonText: "click Me"}

由于buttonText属性仅仅是一个别名,任何针对buttonText的修改斗湖i直接反映到textItem.text。同样,任何对textIten.text的修改都会反映到buttonText,这是一个双向绑定。

由此可以看出,属性别名与绑定表达式不同:

  1. 如果buttonText不是一个别名,相当于将textIten.text绑定到buttonText
  2. textItem.text时,buttonText会随之改变,但是buttonText的变化却不会影响到textItem.text

在使用属性别名时需要注意下面几点:

(1) 属性别名在整个组件初始化完毕之后才是可用的

代码是从上向下执行的,因此一个常见的错误是,在引用所指向的属性还没有初始化的时候就使用了别名。例如,下面的代码无法工作:

property alias buttonText: textItem.text
//下面的代码会报错,因为diamond执行到这里时整个组件还没有完成初始化
buttonText: "some text"

另外,别名不能使用同一个组件中声明的另一个别名,例如,下面的代码是无法工作的:

id: root
property alias buttonText: textItem.text
//下面的代码会报错,因为代码执行到这里,buttonText是一个未定义的值
property alias buttonText2: root.buttonText

正确的初始化方法应该是这样的:

Component.onCompleted: buttonText = "some text"

这里的Component.onCompleted会在组件创建完成时执行。
(2) 属性别名可以与现有的属性同名,但会覆盖现有属性
如下面的例子:

import QtQuickRectangle {id: coloredRectangleproperty alias color: blueRectangle.colorfunction setInternalColor() {color = "#111100";}width: 400height: 300Component.onCompleted: {console.log(coloredRectangle.color);setInternalColor();console.log(coloredRectangle.color);coloredRectangle.color = "#884646";console.log(coloredRectangle.color);}Rectangle {id: blueRectanglecolor: "#1234FF"width: 100height: 100}}

这里在Rectangle中定义了一个color别名属性,它的名称与内建的Rectangle::color属性相同。

使用该组件的任何对象引用color属性时(如代码中额coloredRectangle.color)都使用别名,而不是一般的Rectangle.color属性,而在组件内部直接使用color属性引用的是真实定义的属性,而不是别名。

(3) 引用深度最多为两层,超过两层的引用无效。

例如下面的代码片段的引用是有效的:

property alias color: rectangle.border.colorRectangle{id: rectangle
}

而下面的代码片段的引用是无效的:

property alias color: myItem.myRect.border.colorItem{id: myItemproperty Rectagle myRect
}

需要说明,属性别名在开发组件的时候特别有用。

QML组件通常是一系列基本类型的有序堆积。一个组件可能有很多子对象,对于组件的使用者,处于封装的考虑,不应该知道这些子对象。

然而,组件使用者又不可避免地需要设置某些子对象的属性。此时,可以给子对象属性设置一个别名,把它作为整个组件的属性在外部使用,这样既解决了子对象封装的问题,又将有用的属性暴露出来。

6.默认属性

前面提到,对象声明可以有一个默认属性,默认属性至多有一个。

当声明对象时,如果其子对象没有明确指定它要分配到的属性名,那么这个子对象就被赋值给默认属性。

声明默认属性,只要在属性声明语句的前方加上default修饰符即可。例如:

//MyLabel.qml
Text{default property var someTexttext: "Hello, " + someText.text
}

可以像这样在其他.qml文件中使用MyLabel:

import QtQuick
Rectangle{width:360; height: 360MyLabel{anchors.centerIn: parentText{text: "world!"}}
}

这里Text对象自动成为MyLabel的默认属性的值。这段代码其实等价于:

MyLabel{someText: Text{text: "world!"}
}

由于someText是MyLabel的默认属性,所以无需显式给出这个属性的名字。
其实,在前面的例子已经见过默认属性,例如:

Rectangle{id: retText{text: "Hello, world!"}
}

注意这里的Text对象没有明确指出这个对象赋值给Rectangle的哪一个属性,因此它就会自动成为Rectangle的默认属性的值。

所有基于Item的类型都有一个默认属性dara:list<QtObject>,该属性允许将可视化子对象和资源自由添加到Item对象中。

  • 如果添加的式可视化子对象,那么将作为children
  • 如果添加的是其他对象类型,那么将作为resource

例如:

Item{Text{}Rectangle{}Timer{}
}

相当于

Item{children:[Text{},Rectangle{}]resources:[Timer{}]
}

正因为如此,不需要显式指出将子对象添加到data属性。

7. 必需属性

对象声明中,可以通过required关键字声明一个必需属性,其语法如下:

required property <propertyType> <propertyName>

当创建一个对象的实例时,必需属性是必须要设置的。也可以使用如下语法来使现有的属性成为必需属性:

required <propertyName>

例如下面的代码片段,在自定义的ColorRectanle类型中,颜色属性必需进行设置,不然无法运行:

//ColorRectangle.qml
Rectangle{required color
}

注意,必需属性在模型视图程序中扮演特殊角色:
如果视图的委托具有与视图模型的角色名称相同的属性,则这些属性将使用模型的相应值进行初始化。

8. 只读属性

到目前,声明的属性都是可读可写的。
有时需要使用只读属性,通过指定readonly关键字就可以定义一个只读属性,语法:

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

只读属性必需给出初始值,否则这个属性是没有意义的。一旦只读属性初始化完毕,属性值就不允许再更改。
例如下面的代码是非法的:

Item{readonly property int someNumber: 10Component.onCompleted: someNumber = 20 // 错误
}

注意,只读属性不允许是默认属性,也不允许有别名。

9. 属性修饰符对象(Property Modifier Objects)

一个属性可以拥有与之关联的属性修饰符对象,声明与特定属性相关联的属性修饰符对象的语法如下:

<PropertyModifierTypeName> on <propertyName>

这个通常被称为"on"语法。需要注意的是这个语法实际上是一个对象声明,它会实例化一个对象,而该对象作用于一个已经存在的属性。

典型的用法是动画类型,例如:

Rectangle{width:100; height:100color: "red"NumberAnimation on x{to: 50; duration: 1000}
}

参考书籍:《Qt Quick快速入门 》(霍亚飞)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50992.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(day26)leecode热题——找到字符串中所有字母异位词

描述 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p …

Kubernets——常用命令

Kubernets命令总结 命令说明 命令格式命令说明kubectl run 资源名称 -参数 --image镜像名称:标签创建资源对象&#xff0c;常用参数-i交互&#xff0c;-t终端kubectl get 查询资源 可选参数 -o wide 显示主机信息常用查询的资源 node|deployment|podkubectl exec -it 容器id …

【Git-驯化】一文搞懂git中代码冲突的解决方案大全

【Git-驯化】一文搞懂git中代码冲突的解决方案大全 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff1a…

[C++实战]日期类的实现

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…

ELK安装(Elasticsearch+Logstash+Kibana+Filebeat)

一、简介 1.1、软件简介 ELK其实是Elasticsearch&#xff0c;Logstash 和 Kibana三个产品的首字母缩写&#xff0c;这三款都是开源产品。 1.1.1、Elasticsearch简介 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析…

springboot微信老人健康与饮食管理系统-计算机毕业设计源码82939

基于微信老人健康与饮食管理系统的小程序 摘 要 基于Spring Boot的微信老人健康与饮食管理系统的小程序致力于为老年人提供便捷的健康管理和饮食指导服务。该小程序整合了健康资讯浏览、食谱推荐、健康评估等功能模块&#xff0c;通过系统的设计与实现&#xff0c;旨在帮助老年…

古丝绸之路传闻二:十年败壳精灵显,一介穷神富贵来

古丝绸之路传闻二&#xff1a;十年败壳精灵显&#xff0c;一介穷神富贵来 &#xff08;接上节&#xff1a;古丝绸之路传闻&#xff1a;分内功名匣里财&#xff0c;不关聪慧不关呆&#xff09; 先别说闲话。且说众人带着经纪主人到船上发货&#xff0c;文若虚把之前的事情说了一…

AccessLog| 一款开源的日志分析系统

前言 ClkLog作为分析系列产品中的前端数据分析系统&#xff0c;通过采集前端应用数据进行用户行为分析。其社区版从23年9月发布至今已有近一年&#xff0c;商业版也上线快半年&#xff0c;感谢大家一直以来的关注和支持&#xff0c;ClkLog会继续做好产品升级与服务&#xff0c;…

Linux冯诺依曼体系、操作系统、进程概念、进程状态、进程切换

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;Linux 目录 一、冯诺依曼体系结构 二、操作系统 1、概念 2、为什么要有操作系统&#xff1f; 3、理解操作系统 1.管理的本质 2.管理的概念 3.操作系统结构图 4.为什么要有操作系统&#xff1f; 三…

ASP.NET Core Web深度探讨

ASP.NET Core作为现代Web开发的基石&#xff0c;以其跨平台、高性能和模块化设计的特点&#xff0c;成为许多开发者的首选框架。本文将深入探讨ASP.NET Core在Web开发中的应用&#xff0c;包括MVC、Razor Pages、Blazor等框架的使用&#xff0c;以及路由、中间件、身份认证、会…

golang websocket 手写研究机制

// 处理ws请求 func WsHandler(w http.ResponseWriter, r *http.Request, id string) {var conn *websocket.Connvar err errorpingTicker : time.NewTicker(time.Second * 10)conn, err wsupgrader.Upgrade(w, r, nil)if err ! nil {log.Printf("Failed to set websocke…

python-NLP:2词性标注与命名实体识别

文章目录 词性标注命名实体识别时间命名实体&#xff08;规则方法&#xff09;CRF 命名实体识别方法 词性标注 词性是词汇基本的语法属性&#xff0c;通常也称为词类。词性标注是在给定句子中判定每个词的语法范畴&#xff0c;确定其词性并加以标注的过程。例如&#xff0c;表示…

Python机器学习实战:分类算法之逻辑回归-泰坦尼克号乘客生还预测

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能&#xff0c;从而更快地掌握解决问题所需的能力。 目录 逻辑回归算法介绍 练习题 Python代码与分析 1、读入数据&#xff0c;观察数据情况 2、各属性与生还情况的关联 3、…

用Python做一个翻译软件,比上浏览器快100倍

简单的用Python来做一个翻译软件 开发环境 Python 3.10 Pycharm模块使用 requests -> pip install requests hashlib tkinter案例分为三部分: 1. 爬虫: 获取翻译接口, 请求获取翻译结果问题1: 接口抓包分析问题2: 请求需要写cookie问题3: 不同文本翻译, s加密参数2. 界面…

国科大作业考试资料-人工智能原理与算法-2024新编-第十二次作业整理

袋子里面有3个有偏差的硬币a、b和c,抛掷硬币正面朝上的概率分别是20%、60%和80%。从袋 子里随机取出一个硬币(3个硬币被取出的概率是相等的),并把取出的硬币抛掷3次,得到抛掷结 果依次是X1 , X2和 X3。 a. 画出对应的贝叶斯网络并定义必要的CPT表。 b. 如果抛掷结果是…

PDF解锁网站

https://smallpdf.com/cn/unlock-pdfhttps://smallpdf.com/cn/unlock-pdfhttps://www.freemypdf.comhttps://www.freemypdf.com

【python】python图书管理系统_普通用户+管理员菜单(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

vue vite开发环境https接口代理无法访问的问题

一、问题现象 本地请求是所有的接口前边只需要加一个前缀即可 —— /local/。比如登录接口就是 ‘/local/login’。于是去请求发现直接报错了&#xff0c;报错信息如下&#xff1a; 使用接口代理https接口请求&#xff0c;访问报错的问题&#xff0c;提示如下&#xff1a; http…

[代码审计]记一次简单的java代码审计

如果觉得该文章有帮助的&#xff0c;麻烦师傅们可以搜索下微信公众号&#xff1a;良月安全。点个关注&#xff0c;感谢师傅们的支持。 免责声明 本博客所发布的所有内容&#xff0c;包括但不限于信息、工具、项目以及文章&#xff0c;均旨在提供学习与研究之用。所有工具安全…

FastAPI(七十六)实战开发《在线课程学习系统》接口开发-- 课程详情

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 这个接口用户可以不登录&#xff0c;因为我们的课程随意浏览 那么我们梳理下这里的逻辑 1.根据课程id判断课程是否存在 2.课程需要返回课程的详情 3…