Strange behavior with dynamically removed objects
-
Hello. I'm noted one situation:
OwnLabel.qml
import QtQuick 2.12 import QtQuick.Controls 2.12 Label { text: "Own Label" }
main.qml:
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") property var __ownLabelComponent: Qt.createComponent("OwnLabel.qml") ColumnLayout { RowLayout { Button { text: qsTr("Add") onClicked: { var ownLabel = __ownLabelComponent.createObject(labelsContainter); ownLabel.text += labelsContainter.children.length; } } Button { text: qsTr("Remove") onClicked: { if (labelsContainter.children.length > 0) labelsContainter.children[0].destroy(); console.log(labelsContainter.children.length); } } Button { text: qsTr("Clear & Add New 3") onClicked: { for (var i = 0; i < labelsContainter.children.length; ++i) labelsContainter.children[i].destroy(); for (var j = 0; j < 3; ++j) { var ownLabel = __ownLabelComponent.createObject(labelsContainter); ownLabel.text += labelsContainter.children.length; } console.log(labelsContainter.children.length); } } } ColumnLayout { id: labelsContainter } } }
If you try to click Add, then Remove and then Add, again, it will work correctly:
- output "3,2,1,0"
- 3 elements will be displayed with titles "Own Label 1", "Own Label 2", "Own Label 3"
But, if you try to click "Clean & Add 3" instead of "Clean", you will see:
- output, that container have 6 child elements
- 3 elements will be displayed with titles "Own Label 4", "Own Label 5", "Own Label 6"
So, children.length will not be refreshed until current UI's event (button onClick) has not been done.
(I suspect that faced this situation because QML runs in one thread and all event are staying in one queue)Is there any way to update ".length" property immediately (to use it further in current procedure)?
Thanks!
-
My advise (as most of the time on the forum :P ), would be to not do things like you are doing.
Manipulating UI items is not very mainenable and flexible. You should act on your data instead.I don't really know what is your use case, but most of the time you should avoid using
Qt.createObject
orQt.createComponent
and let view/models class handle the instantiation of your dynamic objects.In your example, you could use a
Repeater
with a model (anint
, a js array, aListModel
, ...). I rewrote it with a ListModel :import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ListModel { id: listModel } ColumnLayout { RowLayout { Button { text: qsTr("Add") onClicked: listModel.append({text: listModel.count + 1}) } Button { text: qsTr("Remove") onClicked: { if (listModel.count > 0) listModel.remove(0); } } Button { text: qsTr("Clear & Add New 3") onClicked: { listModel.clear(); for (var i = 0; i < 3; ++i) { listModel.append({text: listModel.count + 1}) } } } } ColumnLayout { Repeater { model: listModel Label { // you can replace that with OwnLabel text: "My text: %1, my index: %2".arg(model.text).arg(model.index) } } } } }