Details
-
Suggestion
-
Resolution: Unresolved
-
Not Evaluated
-
None
-
None
Description
See the attached example project. It contains 3 similar setups...
- ListView + QAbstractListModel
- Repeater + QAbstractListModel
- ListView + QML list
...where NamedObject is a QML_ELEMENT, and the ListView/Repeater delegates simply show the value of NamedObject.objectName
- For #1 and #2, QAbstractListModel::data() returns a NamedObject* via a custom role
- For #3, the objects are stored in a list<NamedObject>
For each test, the last object in the list is removed and manually destroyed:
Q_INVOKABLE void removeLastObject() { int index = rowCount() - 1; if (index >= 0) { beginRemoveRows({}, index, index); auto obj = m_objects.takeAt(index); endRemoveRows(); obj->deleteLater(); } }
Button { text: "Remove Last Object" onClicked: { let obj = parent.qmlObjects.pop() if (obj) obj.destroy() } }
Outcomes
- For #2 and #3, the delegate is destroyed before the object. Everything is fine.
- For #1, the object is destroyed before the delegate. This produces runtime warnings after the object is destroyed:
TypeError: Cannot read property 'objectName' of null
Suggestion
#1 should also destroy the delegate before the object.
Notes
ListView does support a "remove" transition (https://doc.qt.io/qt-6/qml-qtquick-listview.html#remove-prop ). Applying a transition this would obviously require delegate destruction to be deferred; the suggestion here is to provide immediate destruction only when no "remove" transition is set.