Unable to change parent and child window Z order after calling loader



  • I have a QML application that uses a "Loader":http://qt-project.org/doc/qt-5/qml-qtquick-loader.html" type to load another QML page that creates multiple top-level windows that displays images. I want to be able to change the Z order of the image windows with respect to the main QML application window. This works fine until I use the loader to load another QML file, at which point the relative Z order of the main application window and the image windows becomes locked (e.g. calling raise() on the image window raises both main window and the image windows). Here is a test QML application that shows the problem.

    Main.qml:

    @
    import QtQuick 2.1
    import QtQuick.Window 2.1
    import QtQuick.Controls 1.0
    import QtQuick.Layouts 1.0

    import "."

    Item {
    id: rctMainContainer

    property bool childOnTop: false
    signal reload()
    
    width: 1024
    height: 1024
    
    Rectangle {
        id: rctParent
    
        width: 1024
        height: 1024
        color: "blue"
    
        Item {
            id: itmContent
    
            anchors.fill: parent
    
            Loader {
                id: contentLoader
    
                source: "Container.qml"
    
                anchors {
                    fill: parent
                }
    
                Connections {
                    target: rctMainContainer
    
                    onReload: {
                        contentLoader.source = "";
                        contentLoader.source = "Container.qml";
                    }
                }
    
                Component.onCompleted: {
                    if (contentLoader.status === Loader.Error) {
                        rctParent.color = "red";
                    }
                    else if (contentLoader.status === Loader.Null) {
                        rctParent.color = "magenta";
                    }
                    else if (contentLoader.status === Loader.Ready) {
                        rctParent.color = "green";
                    }
                    else if (contentLoader.status === Loader.Loading) {
                        rctParent.color = "yellow";
                    }
                    else {
                        rctParent.color = "white";
                    }
                }
            }
        }
    
        Button {
            id: btnSwap
    
            width: 100
            height: 36
            anchors{
                top: parent.top
                left: parent.left
                margins:10
            }
    
            visible: true
            enabled: true
    
            Text {
                id: lblSwapText
    
                anchors.fill: parent
                text: "Swap"
            }
    
            onClicked: {
                childOnTop = !childOnTop;
            }
        }
    
        Button {
            id: btnReload
    
            width: 100
            height: 36
            anchors{
                top: btnSwap.bottom
                left: parent.left
                margins:10
            }
    
            visible: true
            enabled: true
    
            Text {
                id: lblReloadText
    
                anchors.fill: parent
                text: "Reload"
            }
    
            onClicked: {
                reload();
            }
        }
    
        Rectangle {
            id: rctHeaderCloseContainer
    
            width: 27
            height: 27
            anchors.right: parent.right
            anchors.top: parent.top
    
            Image {
                id:imgClose
    
                anchors.fill: parent
                source: "../images/close.png"
            }
    
            MouseArea {
                id: btnClose_mouseArea
    
                anchors.fill: imgClose
                cursorShape: Qt.PointingHandCursor;
                onClicked: Qt.quit()
            }
        }
    }
    

    }
    @

    Container.qml

    @
    import QtQuick 2.1
    import QtQuick.Window 2.1
    import QtQuick.Controls 1.0
    import QtQuick.Layouts 1.0

    import "."

    Item {
    id: itmWindowContainer

    Repeater {
        id: rptWindow
    
        model: 2
        anchors.fill: parent
    
        Item {
            id: itmWindow
    
            MyWindow {
                id: winMyWindow
    
                x: 500 + (index*300)
                y: 800 + (index*300)
                width: 300
                height: 300
                visible: true
            }
        }
    }
    

    }
    @

    MyWindow.qml
    @
    import QtQuick 2.1
    import QtQuick.Window 2.1
    import QtQuick.Controls 1.0
    import QtQuick.Layouts 1.0

    Window{
    id: winNew

    flags: Qt.FramelessWindowHint
    
    Connections {
        target: rctMainContainer
    
        onChildOnTopChanged: {
            if (childOnTop) {
                winNew.raise();
            }
            else {
                winNew.lower();
            }
        }
    }
    
    Rectangle {
        id: rctWindow
    
        anchors.fill: parent
        color: "cyan"
    }
    

    }
    @

    To test, save all three QML files into a directory and run "qmlscene main.qml" from the command line inside that directory.

    When the application first opens, you can use the SWAP button to bring the cyan colored windows in front of or behind the main application window. However, after clicking the RELOAD button which loads the same Container.qml file, the cyan colored windows are now locked to appear in front of the main application window.

    Does anyone have any ideas on a way to get around this?

    In case you are wondering why I load the same QML file twice...the real application uses a Loader to load different QML files, and some of those QML files create windows to display images while others do not. The behavior is the same as the test application I provided.



  • BTW, the problem manifests on Win7, but does NOT manifest on Mac, which suggests that perhaps this is a Qt bug.



  • I think what happens is once you reload, the main window becomes active. Then calling raise and lower is raising and lower the main window (and its child) relative to the other windows in the OS. I just experimented and found that changing your onTopChildChanged handler as follows results in the desired behavior (at least under windows 7):
    @ onChildOnTopChanged: {
    if (childOnTop) {
    winNew.requestActivate()
    winNew.raise();
    }
    else {
    winNew.requestActivate()
    winNew.lower();
    }
    }@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.