Abdelilah El Aissaoui
Abdelilah El Aissaoui

Reputation: 5320

Closing qml dialog properly

I've been playing around with dialogs and there is something that bothers me.

I have the following code:

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Button {
        id: click
        x: 285
        y: 189
        text: qsTr("Click")
        onClicked: dlgTest.open()
    }

    Dialog{
        id:dlgTest
        visible:false
        contentItem: Rectangle{
            width: 300
            height: 300
            TextField{
                id: tfText
                anchors.top: parent.top
            }
            Button{
                anchors.top: tfText.bottom
                onClicked: dlgTest.close()
                text: "Close"
            }


        }
    }
}

When I open it the first time I add some text to the TextField and then I close it. However, If I open it again, the text will still be there. What I want is to "reset" the dialog to it's original state when I opened it the first time (with an empty TextField). It seems that calling the method "close" is exactly the same as changing visible to false.

Is there a way of doing this "reset"?

I have an other dialog with a lot of controls and it's annoying having to restore everything manually.

Upvotes: 3

Views: 4546

Answers (1)

derM
derM

Reputation: 13691

In your code you create the Dialog once, as a child of the ApplicationWindow. To 'reset' it, you have two options:

  • Have a reset-function, that you call, and restores everything. You can use this to set it up in the first place as well
  • Create a new Object with everything set in place.

For the latter you can either use JavaScript Dynamic Object Creation or a Loader.

JavaScript Dynamic Object Creation:

Button {
    id: click
    x: 285
    y: 189
    text: qsTr("Click")
    onClicked: {
        var d = diaComp.createObject(null)
        d.open()
    }
}


Component {
    id: diaComp
    Dialog{
        id:dlgTest
        visible:false
        contentItem: Rectangle{
            width: 300
            height: 300
            TextField{
                id: tfText
                anchors.top: parent.top
            }
            Button{
                anchors.top: tfText.bottom
                onClicked: {
                    dlgTest.close()
                    dlgTest.destroy()
                }
                text: "Close"
            }
        }
    }
}

However, as you destroyed the Object, the contents of your properties are lost, and you can't access them anymore. So you need to make sure, to copy them (not bind them) to some property that is not destroyed, first.

With the Loader you have the posibility to unload the Dialog right before you load it again, which basically resets it. But until you unloaded it, you can still access it's values, as you can see in the Buttons onClicked-handler.

Button {
    id: click
    x: 285
    y: 189
    text: qsTr("Click")
    onClicked: {
        console.log((dlgLoad.status === Loader.Ready ? dlgLoad.item.value : 'was not loaded yet'))
        dlgLoad.active = false
        dlgLoad.active = true
        dlgLoad.item.open()
    }
}

Loader {
    id: dlgLoad
    sourceComponent: diaComp
    active: false
}


Component {
    id: diaComp
    Dialog{
        id:dlgTest
        visible:false
        property alias value: tfText.text
        contentItem: Rectangle{
            width: 300
            height: 300
            TextField{
                id: tfText
                anchors.top: parent.top
            }
            Button{
                anchors.top: tfText.bottom
                onClicked: {
                    dlgTest.close()
                }
                text: "Close"
            }
        }
    }
}

Of course, you could also copy the values from the Loader's item as well, and then unload it earlier, to possible free the memory.

But if the Dialog is frequently (most of the time) shown, it might be the wisest to avoid the creation and destruction of the objects, by reusing it and resetting it manually.

Upvotes: 6

Related Questions