QML中ID的范围是什么?

时间:2018-03-16 00:07:59

标签: qt scope qml qt5

该文件称我们不能在一个文件中包含相同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 不同的文件只是我在我的代码中显示,没有错误,我工作。但我怎样才能区分

1 个答案:

答案 0 :(得分:6)

规范的答案是:

  

id的范围是组件范围。

组件范围是:

  

QML文档中的每个QML组件都定义了一个逻辑范围。每   document至少有一个根组件,但也可以有其他组件   内联子组件。组件范围是对象的并集   组件中的ID和组件的根对象属性。

本身对于范围究竟是什么以及如何最佳地利用它本身并不过分提供信息。更多信息:

  

在QML中,组件实例将它们的组件范围连接在一起   形成范围层次结构。组件实例可以直接访问   他们的祖先的组成范围。

基本上,qml文件中的每个id的实现类似于该源的根项的属性。除非无法通过someobj.someId访问,只能通过someId

这意味着,由于qml的动态范围,这个id可以被从根对象扩展的分支中存在的任何对象访问。

只要它没有被名称相同的idproperty遮蔽。

a_item将显示在a.qml以及其根Item增长的分支中存在的任何对象。

它不会在main.qml中显示,因为该对象位于树的下方,其中未定义a_item

在同一思路中,b1可以从a.qml访问,因为b1main.qml中定义,a.qml实例化了b_item。但a1会 从那里看不到。

事实上,由于b1main.qmlid中定义,它是整个应用程序树的根,所以每个对象都可以看到这两个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表示a1a表示a1。由于a.qmla内可见,因此无论您main.qml的哪个a实例,都会引用a_itema的一个实例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}},您应该通过属性,别名实现更通用的使用界面还有什么。