Edit2: The accepted answer demonstrates how the warning should not pose that much of a problem. I have changed the topic of the question to better reflect what is in fact answered there. It did not solve the question of Binding refered to in Edit1, but as the warning does not worry me anymore the primary reason for using Binding is no longer relevant.
Edit: As per Praveen Kumar's suggestion I created a MVCE to illustrate the problem. However, the code now seems to work as intended! However, because the method used has an explicit warning in the documentation, I have added the condition to the question that the solution has to involve the Binding QML Type, which is still something I do not understand how to do.
Modified original question: I have some objects that I create dynamically in QML, and I would like to bind some of these objects' properties to properties of static objects.
I have used a ListModel to manage the dynamically created objects as suggested here.
Using this ListModel I have no problem looping through all the objects and accessing them.
The same site suggests using the Binding component for binding properties, but I do not understand how to use it.
I am able to make this work without the Binding type as the following code demonstrates:
main.qml
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.1
Window {
visible: true
width: 640
height: 480
ListModel
{
id: listModel
}
Column
{
id: mainCol
anchors.centerIn: parent
spacing: 10
Button
{
text: "Click to create object"
onClicked:
{
var component = Qt.createComponent("Box.qml");
var obj = component.createObject(mainCol);
listModel.append({"obj": obj})
}
}
TextField
{
id: inputTxt
}
Button
{
text: "Click to bind properties"
onClicked:
{
for (var i = 0; i < listModel.count; ++i)
{
var dynObj = listModel.get(i).obj;
dynObj.boxTxt = Qt.binding(function() {return inputTxt.text});
}
}
}
}
}
Box.qml
import QtQuick 2.0
Rectangle
{
property alias boxTxt: txt.text
width: 100
height: 100
color: "lightblue"
Text
{
id: txt
text: "Dynamic object"
}
}
This does exactly what I want, but the documentation has this warning about ListModel.get():
Warning: The returned object is not guaranteed to remain valid. It should not be used in property bindings.
which is what I'm doing.
I can not wrap my head around using Binding. Wouldn't I have to dynamically create a new Binding component for each Box component? And would this not get me equally far?
If Binding is not the way to do this, that would be an interesting answer as well!
(Also, if editing the question this way is not the way to do things here, please let me know in a comment)
答案 0 :(得分:0)
很抱歉,我没有时间考虑你的尝试......我真的不知道,为什么你应该为ListModel
添加视觉对象,但可能有原因。 ..
据我所知,这是警告的问题:
警告:不保证返回的对象仍然有效。它不应该用于属性绑定。
所以我想告诉你,由于这个警告,你不应该遇到很多问题。
所以,让我们看看为什么(以及你在做什么)
onClicked: {
var component = Qt.createComponent("Box.qml");
var obj = component.createObject(mainCol);
listModel.append({"obj": obj})
}
在这里,您可以使用mainCol
作为父级创建对象。要将其销毁,您需要销毁mainCol
或明确调用该对象上的destroy()
只要你不这样做,你就不必担心创建对象变得无效。
现在,您向JSObject
添加一个新的ListModel
,其中包含对您新创建的项目的引用。
然后你有:
onClicked:
{
for (var i = 0; i < listModel.count; ++i)
{
var dynObj = listModel.get(i).obj;
dynObj.boxTxt = Qt.binding(function() {return inputTxt.text});
}
}
现在:listModel.get(i)
将返回一个由JS垃圾收集器处理的对象,这意味着,只要没有任何引用它并且GC有运行,对象就会被删除。 (理想情况下。有时GC有点贪心!)
如果现在,你有一个绑定到所述对象,绑定将失去连接(因为这可能不是一个参考,由GC重视),所以这样的东西不是一个好主意:
var dObj = listModel.get(i)
property var x = Qt.binding(function() { return dObj })
但你不能这样做。实际上,您正在使用您之前创建的项目的引用,即您在ListModel
中填充以绑定此Item
的属性。为此,您在行
var dynObj = listModel.get(i).obj;
现在你不需要为那些只需要告诉你引用(由listModel.get(i)
返回)的对象的生命时间而烦恼,因为你有你想要的东西({{ 1}})已分配(不是绑定)。它可能会死,如果它想要,你继续绑定为你想要。
如果不遵循确切的用例,.obj
可能(至少同样)满足您的需求。据我所知,在容器中存储对Items的引用。