Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Destroying dynamically created objects in a loop



  • I have simplified my problem to this simple code. I have a Button in my main window. When it is clicked, it will dynamically create 3 objects of typeMyDialog. When user clicks on the OK button of the dialog, a closed signal is emitted. I connect to this signal in the main window and try to destroy the object. I noticed that when I try to destory the second and third dialogs, I get this message in the console

    qrc:/main.qml:19: TypeError: Property 'destroy' of object TypeError: Type error is not a function

    I think this error is indicating that I am trying to free the same memory location multiple times. I am wondering how I can fix this issue. I know I can have MyDialog destroy itself but I want to do it in main.qml. Thanks in advance for your help

    Here is my code

    // main.qml
    
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Window 2.15
    
    Window {
        width: 640
        height: 480
        visible: true
    
        Button {
            id: button
            anchors.centerIn: parent
            text: "Generate 3 Message dialogs"
    
            onClicked: {
                var component = Qt.createComponent("qrc:/MyDialog.qml")
                for(var ii = 0; ii < 3; ++ii) {
                    var object = component.createObject(button)
                    // Connecting to the closed signal of MyDialog
                    object.closed.connect(()=>{object.destroy()})
                }
            }
        }
    }
    

    and

    // MyDialog.qml
    
    import QtQuick 2.15
    import QtQuick.Dialogs 1.3
    
    Item {
        id: root
        signal closed()
    
        MessageDialog {
            text: "I am a dialog"
            visible: true
            standardButtons: StandardButton.Ok
            // closed() signal is emitted once the user hits Ok
            onAccepted: root.closed()
        }
    }
    


  • @aShahba said in Destroying dynamically created objects in a loop:

    I have simplified my problem to this simple code. I have a Button in my main window. When it is clicked, it will dynamically create 3 objects of typeMyDialog. When user clicks on the OK button of the dialog, a closed signal is emitted. I connect to this signal in the main window and try to destroy the object. I noticed that when I try to destory the second and third dialogs, I get this message in the console

    qrc:/main.qml:19: TypeError: Property 'destroy' of object TypeError: Type error is not a function

    I think this error is indicating that I am trying to free the same memory location multiple times.

    That is what is happening. The root of the problem is that var object is captured in each arrow function, rather than object's value at the time the closure is defined.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#creating_closures_in_loops_a_common_mistake



  • You dont need to do a connection in main.qml, just call destroy() in the object when the buttom is clicked:

    onAccepted: root.destroy()
    


  • @johngod I know how to have the dialog do self-destruction when accepted signal is emitted. As mentioned in the post, I want to do it in main.qml though.

    On a sidenote, the problem with self-destruction is that it is only valid if the item is created dynamically. As you can imagine, it is not guaranteed that MyDialog is always created dynamically.



  • @aShahba said in Destroying dynamically created objects in a loop:

    I have simplified my problem to this simple code. I have a Button in my main window. When it is clicked, it will dynamically create 3 objects of typeMyDialog. When user clicks on the OK button of the dialog, a closed signal is emitted. I connect to this signal in the main window and try to destroy the object. I noticed that when I try to destory the second and third dialogs, I get this message in the console

    qrc:/main.qml:19: TypeError: Property 'destroy' of object TypeError: Type error is not a function

    I think this error is indicating that I am trying to free the same memory location multiple times.

    That is what is happening. The root of the problem is that var object is captured in each arrow function, rather than object's value at the time the closure is defined.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#creating_closures_in_loops_a_common_mistake



  • @aShahba said in Destroying dynamically created objects in a loop:

    @johngod I know how to have the dialog do self-destruction when accepted signal is emitted. As mentioned in the post, I want to do it in main.qml though.

    On a sidenote, the problem with self-destruction is that it is only valid if the item is created dynamically. As you can imagine, it is not guaranteed that MyDialog is always created dynamically.

    Inline components are useful for doing this in a more declarative fashion.

    Button {
        Component {
            id: inlineComponent
            MyDialog { onClosed: this.destroy() }
        }
        onClicked: inlineComponent.createObject(this)
    }
    

Log in to reply