QML中ID的范围是什么?

Ryo*_*you 3 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
  }
}
Run Code Online (Sandbox Code Playgroud)

我的问题:

1.

QML中ID的范围是什么?在我的测试中,结果显示Item无法访问其孩子及其兄弟的孩子的身份,但可以访问他的父母或兄弟,对吧?

2.

同一ID不同的文件只是我表现出我的代码,没有错误,我的工作.但我怎样才能区分它们.

dte*_*ech 9

规范的答案是:

ids 的范围是组件范围.

组件范围是:

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

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

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

基本上,idqml文件中的每个文件都被实现,就像该源的根项的属性一样.除非它无法通过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了整个应用程序树的根,所以这两个ids将从应用程序的每个对象可见,只要它是对象树的一部分并且只要标识符不是阴影.请注意,它们不会从单例或无父对象中看到,因为它们不是应用程序对象树的一部分.

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
Run Code Online (Sandbox Code Playgroud)

对于属性也是如此,尽管动态范围仅适用于为qml文件根元素定义的属性,不像ids是可见的,即使它们位于不同的子分支上,这就是为什么在这个答案的第一句中我把它作为"实现了该源的根项的属性":

Obj
  Obj
    Obj
      id: objid
      property objprop
  CustomObj
Run Code Online (Sandbox Code Playgroud)

因此objid它将是可见的CustomObj,但objprop不会,因为它不是一个id而没有在根对象中定义.该id等同于这样做:

Obj
  property objid : _objid
  Obj
    Obj
      id: _objid
Run Code Online (Sandbox Code Playgroud)

id来自给定源的所有内容在qml源根对象的上下文中都是可见的,随后是最终将下拉到此上下文的所有其他内容,因为它查找无法解析"更高"上下文中的标识符.

最后,请记住微妙的陷阱 - id如果您确定应用程序将在兼容的上下文树中实例化对象,则只能跨源使用.

例如:

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
Run Code Online (Sandbox Code Playgroud)

陷阱继续 - 上下文树出现在对象树之前 - 创建对象的上下文很重要,一旦设置就无法更改(根据上下文依赖性对重新定义设置某些限制).

// 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()
        }
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

正如这个实际示例所示,即使在两种情况下,新创建的对象都是具有objA标识符的同一对象的父级,但是创建的对象main.qml无法解析它,因为它是在objA尚未定义的上下文中创建的,但它可以正常工作如果对象是在上下文中创建的objA,那么它即使在树上更高的地方也会被激活.

为了以更通用的方式,它在id源的根对象的上下文中变得可见,并且在每个后续子上下文中保持可见,直到它被具有相同名称的对象遮蔽.可见性无法将树向下到达id定义上下文之前存在的上下文.注意细微差别 - a_item指的是Itemwhile a1指的是a.而且,由于a1是可见里面a.qml它总是引用的一个例子a就是在main.qml,不管是哪个的情况下a,你可能会在,而a_item将涉及到不同对象的每个不同的实例a.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 
Run Code Online (Sandbox Code Playgroud)

动态范围化ids非常有用,可以缩短实现变通方法以获取所需内容的时间.这也是为什么给出id描述性名称而不仅仅是一个非常好的主意main.

例如,如果你有一个manager管理一些数量的数量views,每个数量都包含objects在其中,你可以快速访问各自的相应数据view,object并且无需实现任何其他内容即可访问经理.manager必须遵循的原则是必须首先,然后每个都view应该在它的上下文中创建manager,不一定直接在其中,但在其中,每个都object应该在a的上下文中创建view.当然要注意不要掩盖事物.如果你打破这个规则,事情将无法正常解决.

View.qml { id: view }

manager
  view1
    object // view is view1
  view2
    object // view is view2
  view3
    object // view is view3
Run Code Online (Sandbox Code Playgroud)

当然,这只在特定目的设计中才有意义,在这些设计中,您知道上下文树的一般结构是什么样的.如果您正在制作几乎可以在任何地方使用的通用元素,那么您绝对不应该依赖于id跨源访问,并且您应该通过属性,别名和诸如此类的东西来实现更通用的使用界面.