3

I have a QML component with a property and a default value. If I instantiate this component and overriding the value of the component, the previous, default value is not destroyed.

Example:

The QML component, MyComponent.qml

import QtQuick 2.12

Item {
  property MyResource resource: MyResource {
    name: "B"
  }
}

MyResource.qml

import QtQuick 2.12

QtObject {
  property string name: "Default"
  Component.onCompleted: console.log("Created MyResource", name, this);
  Component.onDestruction: console.log("Destroyed MyResource", name, this);
}

And Root.qml to instantiate the component:

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
  width: 300
  height: 300

  MyComponent {
    resource: MyResource {
      name: "A"
    }
  }
}

Output of qml Root.qml:

qml: Created MyResource A MyResource_QMLTYPE_0(0x5645cc25b770)
qml: Created MyResource B MyResource_QMLTYPE_0(0x5645cc2a1f60)

The default value (the MyResource with the name "B") is never deleted. This behavior is the same when using a C++ QObject instead of MyResource. Manually calling the garbage collector (QJsEngine::collectGarbage) doesn't help.

I tried in Qt 5.15 and Qt 6.4.2.

How can I get rid of the default value of the property?

1 Answer 1

0

It seems that when you create an instance of your object it also instnatiate a version for the component definition. When I tested your component in a ListView, I can see it creating both the "B" and "A" at the same time as well as destroy "B" and "A" at the same time:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    ListView {
        id: _console
        anchors.fill: parent
        model: ListModel { id: consoleModel }
        delegate: Label { text: txt }
        function clear() { consoleModel.clear() }
        function log(...args) {
            var txt = args.join(" ");
            consoleModel.append({txt});
        }
    }
    ListView {
        id: iii
        model: 0
        delegate: MyComponent {
            resource: MyResource { name: "A" }
        }
    }
    component MyComponent: Item {
        property MyResource resource: MyResource { name: "B" }
    }
    component MyResource: QtObject {
        property string name: "Default"
        Component.onCompleted: _console.log("Created MyComponent", name, this);
        Component.onDestruction: _console.log("Destroyed MyComponent", name, this);
    }
    footer: Frame {
        RowLayout { 
            Button { text: "Create"; onClicked: iii.model = 1 }
            Button { text: "Delete"; onClicked: iii.model = 0 }
            Button { text: "GC"; onClicked: gc() }
            Button { text: "Clear"; onClicked: _console.clear() }
        }
    }
}

You can Try it Online!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.