破坏的递归实例化检查

时间:2016-08-28 18:36:04

标签: qt recursion delegates qml cross-reference

我注意到QML在下面有一些未指明的问题 - 当委托试图实例化包含它的对象(委托就是)。

考虑这个简单的树构建器示例:

// Object.qml
Row {
  property int c : 0
  Rectangle {
    width: 50
    height: 50
    color: "red"
    border.color: "black"
    MouseArea {
      anchors.fill: parent
      acceptedButtons: Qt.LeftButton | Qt.RightButton
      onClicked: {
        if (mouse.button === Qt.LeftButton) c++
        else if (c) c--
      }
    }
  }
  List { model: c }
}

// List.qml
Column {
  property alias model : r.model
  Repeater {
    id: r
    delegate: Object {} // wont work
  }
}

在此示例中,Object包含List,其中包含一个实例化另一个Object的委托。然而,它没有工作,没有错误消息,即使在调试模式下,应用程序窗口根本不会出现,而且从内存使用的外观来看,它无可救药地被遗忘在某处。它也不会崩溃。它只是没有用。

我首先怀疑这是QML的短视实施细节中的另一个,其高尚目标是防止意外无限递归。但是,在这种情况下不存在这样的危险,因为即使两个对象相互实例化,该过程也由"模型"控制。

它也恰好工作"完美无缺"如果"间接"添加,例如:

Column {
  property alias model : r.model
  Repeater {
    id: r
    delegate: Loader { source: "Object.qml" }
  }
}

如果代理人从Object替换为代理Loader的{​​{1}},则可以正常使用,我认为因为它不会触发愚蠢的交叉引用检查哪个中断执行。

enter image description here

你可能会问为什么我根本不使用第二种情况,而答案很简单 - 这是一个简单的例子,它可以,但在我的实际生产代码中,这打破了我用级联制作的非常复杂的东西负xy空间中的子项目数量,并在其间插入Object只会导致它被杀死,而我却找不到让它工作的方法。

我还注意到委托在从同一个源,交叉引用或自引用中的Loader实例化树示例时有完全相同的问题 - 当使用这种类型的实例化递归时,应用程序会卡住同样的方式 - 没有错误,没有警告,没有崩溃,没有窗口,没有任何东西。

知道发生了什么以及如何解决这个问题?我的钱是无限递归保护,假设它是无限的,即使它实际上是受控制的,也是非常有限的递归。

编辑:另请注意,以这种方式包装它并不会Component。它仅在delegate: Component { Object {} }未被引用为实例时才有效,因此无论实际情况如何,它看起来都是非常肤浅的检查对象是否相互包含。正如预期的那样,如果包装被移动到Object

,它也可以工作
Object

更新:

我也注意到了这一点:

 Loader {
   Component.onCompleted: setSource("List.qml", {"model": Qt.binding(function() {return c})})
 }

哪个也不起作用。这次在控制台中有一些实际输出,说// Obj.qml Item { id: main property Obj thisObj : main } 真的不是,因为它在类型属性的上下文中使用,而不是值/实例。

似乎递归实例化在QML中进行检查并且从根本上打破了,如果在对象树的主体中找到文字QML元素类型自/交引用,它们就完全没有产生任何内容,并且当它引用时产生错误输出用于指定属性类型,即使QML对象属性实际上实现为引用而不是实例。

我还发布了一个bug report并提出如何区分实际的无限递归和自我或交叉引用的情况,实际上无限递归,这很简单 - 只需要#&# 39;如果引用是属性类型或代理内部,则触发。

0 个答案:

没有答案