QML- QML作用域和命名解析
创始人
2025-05-29 09:45:54

Q 理论使用总结

  • 一、概述
  • 二、JavaScript范围
  • 三、类型名称和导入的JavaScript文件
  • 四、绑定作用域对象
  • 五、Component 组件范围
  • 六、组件实例层次结构
  • 七、覆盖的属性
  • 八、JavaScript全局对象

一、概述

QML属性绑定、内联函数和导入的JavaScript文件都在JavaScript作用域中运行。作用域控制一个表达式可以访问哪些变量,以及当两个或多个变量名称冲突时,哪个变量优先访问。

由于JavaScript的内置作用域机制非常简单,QML对其进行了增强,以更自然地适应QML语言扩展。

二、JavaScript范围

QML的作用域扩展不会干扰JavaScript的自然作用域。JavaScript程序员在使用QML编写函数、属性绑定或导入的JavaScript文件时,可以重用他们现有的知识。

在下面的例子中,addConstant()方法会在传入的参数上加上13,就像程序员预期的那样,而不管QML对象的a和b属性是什么值。

  QtObject {property int a: 3property int b: 9function addConstant(b) {var a = 13;return b + a;}}

QML遵守JavaScript的正常作用域规则,甚至适用于绑定。这种完全离谱的绑定将12赋值给QML对象的a属性。

  QtObject {property int aa: { var a = 12; a; }}

QML中的每个JavaScript表达式、函数或文件都有自己独特的变量对象。在一个地方声明的局部变量永远不会与在另一个地方声明的局部变量冲突。

三、类型名称和导入的JavaScript文件

QML文档包括定义类型名称和文档可见的JavaScript文件的import语句。除了在QML声明中使用之外,JavaScript代码在访问附加属性和枚举值时也会使用类型名。

导入的效果适用于QML文档中的每个属性绑定和JavaScript函数,即使是嵌套的内联组件。下面的例子展示了一个简单的QML文件,它访问一些枚举值并调用导入的JavaScript函数。

  import QtQuick 2.0import "code.js" as CodeListView {snapMode: ListView.SnapToItemdelegate: Component {Text {elide: Text.ElideMiddletext: "A really, really long string that will require eliding."color: Code.defaultColor()}}}

四、绑定作用域对象

具有属性绑定的对象称为绑定的范围对象。在下面的例子中,Item对象是绑定的作用域对象。

Item {anchors.left: parent.left
}

绑定可以不受限制地访问范围对象的属性。在前面的例子中,绑定直接访问项的parent属性,而不需要任何形式的对象前缀。QML为JavaScript引入了一种更结构化、更面向对象的方法,因此不需要使用JavaScript的this属性。

从绑定中访问附加的属性时必须小心,因为它们与作用域对象交互。概念上的附加属性存在于所有对象上,即使它们只对其中的一个子集有影响。因此,未限定的附加属性读取总是解析为作用域对象上的附加属性,这并不总是程序员想要的。

例如,PathView类型会根据委托在路径中的位置来添加插入的值属性。由于PathView只有意义地将这些属性附加到委托中的根对象上,因此任何访问它们的子对象都必须显式限定根对象,如下所示。

PathView {delegate: Component {Rectangle {id: rootImage {scale: root.PathView.scale}}}
}

如果Image对象省略了根前缀,它会无意中访问未设置的PathView。在自身上附加属性。

五、Component 组件范围

QML文档中的每个QML组件定义一个逻辑范围。每个文档至少有一个根组件,但也可以有其他内联子组件。组件的作用域是组件内部对象id和组件根对象属性的联合。

Item {property string titleText {id: titletypetext: "" + title + ""font.pixelSize: 22anchors.top: parent.top}Text {text: titletype.textfont.pixelSize: 18anchors.bottom: parent.bottom}}

上面的示例显示了一个简单的QML组件,该组件在顶部显示富文本标题字符串,在底部显示相同文本的较小副本。第一种文本类型在形成要显示的文本时直接访问组件的title属性。根类型的属性是可以直接访问的,这使得在整个组件中分发数据变得很容易。
第二种文本类型使用id直接访问第一种文本。id由QML程序员显式指定,因此它们总是优先于其他属性名(JavaScript作用域中的属性名除外)。例如,在前面的例子中,即使绑定的作用域对象有titletype属性,titletype id仍然优先。

六、组件实例层次结构

在QML中,组件实例将它们的组件作用域连接在一起形成作用域层次结构。组件实例可以直接访问它们祖先的组件作用域。
演示这一点的最简单方法是使用内联子组件,其组件作用域隐式地作为外部组件的子组件。

Item {property color defaultColor: "blue"ListView {delegate: Component {Rectangle {color: defaultColor}}}
}

组件实例层次结构允许委托组件的实例访问Item类型的defaultColor属性。当然,如果委托组件有一个名为defaultColor的属性,它就会优先。

组件实例作用域层次结构也扩展到越界组件。在下面的例子中,标题页。qml组件创建两个TitleText实例。尽管TitleText类型位于一个单独的文件中,但在TitlePage中使用title属性时,仍然可以访问到它。QML是一种动态作用域的语言——根据在哪里使用,title属性的解析方式可能不同。

// TitlePage.qmlimport QtQuick 2.0Item {property string titleTitleText {size: 22anchors.top: parent.top}TitleText {size: 18anchors.bottom: parent.bottom}}// TitleText.qmlimport QtQuick 2.0Text {property int sizetext: "" + title + ""font.pixelSize: size}

动态作用域非常强大,但必须谨慎使用,以防止QML代码的行为变得难以预测。

一般来说,它应该只在两个组件已经以另一种方式紧密耦合的情况下使用。在构建可重用组件时,最好使用属性接口,如下所示:

// TitlePage.qmlimport QtQuick 2.0Item {id: rootproperty string titleTitleText {title: root.titlesize: 22anchors.top: parent.top}TitleText {title: root.titlesize: 18anchors.bottom: parent.bottom}}// TitleText.qmlimport QtQuick 2.0Text {property string titleproperty int sizetext: "" + title + ""font.pixelSize: size}

七、覆盖的属性

QML允许在对象声明中定义的属性名被另一个对象声明中声明的属性覆盖,该对象声明扩展了第一个对象声明。例如:

  // Displayable.qmlimport QtQuick 2.0Item {property string titleproperty string detailText {text: "" + title + "
" + detail}function getTitle() { return title }function setTitle(newTitle) { title = newTitle }}// Person.qmlimport QtQuick 2.0Displayable {property string titleproperty string firstNameproperty string lastNamefunction fullName() { return title + " " + firstName + " " + lastName }}

在这里,title既被赋予了输出文本的标题以供显示,也被赋予了Person对象的敬语标题。

根据引用被覆盖属性的范围解析该属性。在Person组件的作用域中,或者在引用Person组件实例的外部作用域中,title解析为Person.qml中声明的属性。fullName函数会引用Person内部声明的title属性。

然而,在Displayable组件中,title指向Displayable.qml中声明的属性。getTitle()和setTitle()函数以及对text对象的text属性的绑定都将引用Displayable组件中声明的title属性。
尽管名称相同,但这两个属性是完全独立的。其中一个属性的onChanged信号处理程序不会因同名的另一个属性发生更改而触发。其中一个属性的别名只能引用其中一个属性,不能同时引用两个属性。

八、JavaScript全局对象

QML不允许类型、id和属性名与全局对象上的属性冲突,以防止混淆。Math.min(10, 9) 将始终按预期工作。

相关内容

热门资讯

一杯热牛奶的治愈力:乳业如何在... 随着气候的异常,这个冬天很多人都感到忽冷忽热,免疫力下降,数据也证明了这一点。 2025年第49周中...
天津市最新或2023(历届)征... 从天津市征兵办获悉,今冬天津市征兵工作开始部署安排,10月份随着“征兵宣传月”活动的启动,今冬征兵报...
滨海新区最新或2023(历届)... 昨日,滨海新区冬季征兵工作正式启动,征兵的时间从现在起到年底前结束。今年()的征集对象、范围、身体条...
天津最新或2023(历届)冬季... 近日,天津市召开征兵工作会议,部署安排今冬征兵任务。今年本市征兵将把新兵政治质量摆在首位,严格落实三...
天津市最新或2023(历届)招... 天津市人民政府征兵办公室招收士官启事 根据天津市人民政府、天津警备区安排部署,我办公室...