Search code examples
qtqmlqtquick2qtquickcontrols2

Open and close additional window (QML)


Currently I have a window openning in the following way:

property variant win
Button {
    id: testButton
    MouseArea {
        onClicked: {
            var component = Qt.createComponent("test.qml");
            win = component.createObject(testButton);
            win.show();
        }
    }
}
  1. Is it ok to create a window like this or there is a better way to do it (from QML, not from C++)?

  2. When I close this additional window (just by clicking "x" button), I want to connect it to another event (for example, changing color of the button). How to do it?

Thanks.


Solution

  • It is usually nicer to have it more declarative. If you want your button to only open one window, the usage of a Loader might be right for you.
    I think this is what you want, as you store it in one variable, and if you click the button multiple times, you would lose access to your instance. If you need a larger amount of Windows created by the same Button, you might use a ListModel and a Instantiator to create the instances.

    With the Loader this might look like this:

    Button {
        id: ldbutton
        onClicked: winld.active = true
        Rectangle {
            id: ldindic
            anchors {
                left: parent.left
                top: parent.top
                bottom: parent.bottom
            }
            width: height
            color: winld.active ? 'green' : 'red'
        }
    
        Loader {
            id: winld
            active: false
            sourceComponent: Window {
                width: 100
                height: 100
                color: 'green'
                visible: true
                onClosing: winld.active = false
            }
        }
    }
    

    In this code is also already the answer to your second question: The signal you are looking for is called closing - connect to it to do what ever is necessary.

    In the case of the Loader it is necessary to unload the window, so it can be loaded again later, maybe. If you have the window created by a Instantiator, you need to remove the corresponding index from the Instantiator's ListModel.

    This might look like this:

    Button {
        id: rpbutton
        onClicked: rpmodel.append({})
        text: 'Open Windows ' + rpmodel.count
    
        ListModel {
            id: rpmodel
        }
    
        Instantiator { // from QtQml 2.0
            model: rpmodel
            delegate: Window {
                width: 100
                height: 100
                color: 'blue'
                visible: true
                onClosing: rpmodel.remove(index)
            }
        }
    }
    

    In your code you could connect to it, either by using a Connection-object, that connects to your property win, or by changing the JS onClicked like so:

    onClicked: {
        var component = Qt.createComponent("test.qml");
        win = component.createObject(testButton);
        win.closing.connect(function() { console.log('do something') })
        win.show();
    }