该文件称我们不能在一个文件中包含相同ID 。这意味着我们可以在不同的文件中拥有相同的ID,对吧?我不知道QML中ID的范围,所以我编写如下代码来测试它。
//a.qml
Item {
id: a_item
x:20;
y:b_item.x // cannot access this id
y:b1.x1 // can access
Item {
id:a1
x:20
Component.onCompleted : a1.x //this a1 is a.qml's a1 not the a1 in main.qml
}
}
//b.qml
Item {
id: b_item
x:20;
property int x1: 30;
}
//main.qml
Item {
a {
id:a1
Component.onCompleted : b1.x = 1 //can access
}
b {
id:b1
}
function() {
a_item.x = 1; // cannot access this id
}
}
我的问题:
1
QML中ID的范围是什么?在我的测试中,结果显示Item无法访问其孩子及其兄弟的孩子的身份,但可以访问他的父母或兄弟,对吗?
2
同一个ID 不同的文件只是我在我的代码中显示,没有错误,我工作。但我怎样才能区分。答案 0 :(得分:6)
规范的答案是:
id
的范围是组件范围。
组件范围是:
QML文档中的每个QML组件都定义了一个逻辑范围。每 document至少有一个根组件,但也可以有其他组件 内联子组件。组件范围是对象的并集 组件中的ID和组件的根对象属性。
本身对于范围究竟是什么以及如何最佳地利用它本身并不过分提供信息。更多信息:
在QML中,组件实例将它们的组件范围连接在一起 形成范围层次结构。组件实例可以直接访问 他们的祖先的组成范围。
基本上,qml文件中的每个id
的实现类似于该源的根项的属性。除非无法通过someobj.someId
访问,只能通过someId
。
这意味着,由于qml的动态范围,这个id可以被从根对象扩展的分支中存在的任何对象访问。
只要它没有被名称相同的id
或property
遮蔽。
a_item
将显示在a.qml
以及其根Item
增长的分支中存在的任何对象。
它不会在main.qml
中显示,因为该对象位于树的下方,其中未定义a_item
。
在同一思路中,b1
可以从a.qml
访问,因为b1
在main.qml
中定义,a.qml
实例化了b_item
。但a1
会
从那里看不到。
事实上,由于b1
和main.qml
在id
中定义,它是整个应用程序树的根,所以每个对象都可以看到这两个obj tree a1 b1 a_item b_item
main.qml D D X X
a.qm V V D X
Item a1 V V V X
b.qml V V X D
D - defined here, V - visible here, X - not available
应用程序的一部分,只要它是对象树的一部分,并且只要标识符没有被遮蔽。请注意,它们不会从单例或无父对象中看到,因为它们不是应用程序对象树的一部分。
id
对于属性也是如此,尽管动态范围仅适用于为qml文件根元素定义的属性,与Obj
Obj
Obj
id: objid
property objprop
CustomObj
不同,即使它们位于不同的子分支上也是可见的,这是为什么在这个答案的第一句中我把它作为"实现了该来源的根项目的属性":
objid
因此CustomObj
中将显示objprop
,但id
将不会显示{1}},因为它不是ID,也未在根对象中定义。 Obj
property objid : _objid
Obj
Obj
id: _objid
与执行此操作完全相同:
id
来自给定源的所有id
在qml源根对象的上下文中都是可见的,随后在查找无法解析&中的标识符时最终将下拉到此上下文的所有其他内容#34;更高"上下文。
最后,请记住微妙的陷阱 - 如果您确定应用程序将在兼容的上下文树中实例化对象,则只能跨源使用A.qml {
id: objA
B { } // objA will be visible to this object
}
main.qml
A {
B {} // objA will NOT be visible to this object
}
B {} // objA will NOT be visible to this object
。
例如:
// ObjA.qml
Item {
id: objA
Component {
id: cm
ObjB {}
}
function create() { cm.createObject(objA) }
}
// ObjB.qml
Item {
Component.onCompleted: console.log(objA)
}
// main.qml
Component {
id: cm
Rect {}
}
Obj {
anchors.fill: parent
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.LeftButton) {
cm.createObject(parent)
} else {
parent.create()
}
}
}
}
陷阱继续 - 上下文树出现在对象树之前 - 创建对象的上下文很重要,一旦设置就无法更改(对重新定位有一些限制)取决于上下文依赖性。)
objA
正如这个实际示例所示,即使在两种情况下,新创建的对象都是具有main.qml
标识符的同一对象的父级,但objA
中创建的对象无法解析它,因为它是在objA
尚未定义的上下文中创建,但如果对象是在id
的上下文中创建的,它就会起作用,即使它在树上更高的地方也会被激活。
为了以更通用的方式放置,id
在源的根对象的上下文中变得可见,并且在每个后续子上下文中保持可见,直到它被具有相同名称的对象遮蔽为止。 。可见性无法将树向下到达定义a_item
的上下文之前存在的上下文。
请注意细微差别 - Item
表示a1
而a
表示a1
。由于a.qml
在a
内可见,因此无论您main.qml
的哪个a
实例,都会引用a_item
中a
的一个实例be in,而a_item
将为a
的每个不同实例引用不同的对象。 a1
是"亲戚"并且在a
的每个不同实例中都会有所不同,但a1
是绝对的,并且始终引用a_item
的特定实例。这是因为// Obj.qml
Item {
id: obj
Component.onCompleted: console.log(obj === oid)
}
// main.qml
Obj { } // false
Obj { id: oid } // true
是一个具体的实例,而id
是一个类型/原型。
id
动态范围main
可能非常有用,可以缩短实施变通方法以获取所需内容的时间。这也是为什么提供manager
描述性名称而不仅仅是views
是一个非常好的主意。
例如,如果您有objects
管理多个view
,其中每个object
都有manager
,您就可以快速访问相应的view
对于每个manager
,也可以访问经理而无需实施任何其他内容。经验法则是object
必须先行,然后每个view
应该在View.qml { id: view }
manager
view1
object // view is view1
view2
object // view is view2
view3
object // view is view3
的上下文中创建,不一定直接在其中,但在其中,每个id
应在{{1}}的上下文中创建{{1}}。当然要注意不要掩盖事物。如果你打破了这个规则,事情将无法妥善解决。
{{1}}
当然,这只在特定目的设计中才有意义,在这些设计中,您知道上下文树的一般结构是什么样的。如果您正在制作几乎可以在任何地方使用的通用元素,那么绝对不依赖于跨源访问{{1}},您应该通过属性,别名实现更通用的使用界面还有什么。