Open and close additional window (QML)

2019-07-18 15:26发布

问题:

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.

回答1:

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();
}