qtqmlqtquick2qt5.5

QML GridLayout does not obey my specified cell arrangements


In this code, some items are invisible at first. I want them to be visible on the click of a button at the place where they have been placed by me.

In order to leave space for them, I have placed the other item where it will be shown when hidden options will be visible.

My problem is that GridLayout does not obey the following cell positions set in code when other items are invisible.

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1

Window {
    visible: true
    height: 500; width: 500

    GridLayout {
        id: gridLayout

        property bool secondScreenOptionsVisible: false

        property int hmmiButtonRow: 0
        property int hmmiButtonCol: 0

        Rectangle {
            id: hmmi; visible: gridLayout.secondScreenOptionsVisible
            Layout.row: gridLayout.hmmiButtonRow; Layout.column: gridLayout.hmmiButtonCol;
            height: 50; width: 50; color: "pink";
            Layout.alignment: Qt.AlignTop
            Text { text: "HMMI"; anchors.centerIn: parent }
        }

        property int optionsButtonRow: 1
        property int optionsButtonCol: 0

        Rectangle {
            id: optionsButton; visible: gridLayout.secondScreenOptionsVisible
            Layout.row: gridLayout.optionsButtonRow; Layout.column: gridLayout.optionsButtonCol;
            height: 50; width: 50; color: "red"
            Layout.alignment: Qt.AlignTop
            Text { text: "Options..."; anchors.centerIn: parent }
        }

        property int flipperControlRow: 3
        property int flipperControlCol: 0

        Rectangle {
            id: flipperControl;
            Layout.row :gridLayout.flipperControlRow; Layout.column: gridLayout.flipperControlCol;
            height: 200; width: 50;
            color: "brown";
            Layout.rowSpan: 4
            Layout.alignment: Qt.AlignTop
            Text { text: "Flipper"; anchors.centerIn: parent }
        }
    }
}

Output:

When all the items are visible:

enter image description here

When other two items are hidden, the GridLayout does not obey the rules.

enter image description here

I want GridLayout to obey the cell positions set by me, irrespective of whether other items are visible or not.

Please help.


Solution

  • The doc says for GridLayout that:

    [...] It is similar to the widget-based QGridLayout. All visible children of the GridLayout element will belong to the layout. [...].

    So what you are seeing is a direct consequence of the implementation approach followed by developers. Indeed a change in visibility triggers Items repositioning, as can be seen in this code path.

    Instead of considering visible property you can use opacity property: the non-opaque Items are taken in account by the layout, resulting in the expected visible behaviour. See for instance this simple example:

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    
    Window {
        visible: true
        height: 400; width: 400
    
        GridLayout {
            anchors.fill: parent
            id: gridLayout
            rows: 3
            columns: 3
    
            Repeater {
                id: rep
                model: 9
    
                Rectangle {
                    color: "black"
                    Layout.preferredWidth: 100
                    Layout.preferredHeight:  100
                    Layout.alignment: Qt.AlignCenter
                    opacity: index === rep.count - 1
                }
            }
        }
    }
    

    Mind that non-opaque Items are still rendered, differently from invisible ones, with a varying degree of impact over performances, depending on your actual use case.