Rectangle does not fill height with other components in Layout [QML]

Viewed 36

This is what I have

What I have

This is what I want

What I want

my qml :

ColumnLayout
{
    anchors.fill: parent
    anchors.topMargin: 10
    anchors.bottomMargin: 10
    anchors.rightMargin: 10
    anchors.leftMargin: 10
    spacing: 10
    
    Rectangle
    {
        Layout.fillWidth: true
        Layout.fillHeight: true
        color : "#600000"
        border : 20
    }
    Button
    {
        Layout.fillWidth: true
        Layout.fillHeight: true
        text: "Button1" 
    }
    Button
    {
        Layout.fillWidth: true
        Layout.fillHeight: true
        text: "Button2" 
    }
}

The problem with the above layout, is that I want the Rectangle to fill 1/3 of the screen. Right now it fills maybe only 10 pixels worth of height. When I have several components in a layout, I personally expect them to fill each as much as the other. Since I know I will add more button, remove others, I don't want to just take the Layout.preferredHeight : parent.height/3. this will require lots of maintenance long term.

another thing I don't understand : 2 rectangle together will separate their space half half. 2 buttons will do the same. But as soon as I mix those two components, the button seem to take 95% of the height as opposed to the rectangle.

2 Answers

Button has implicitHeight defined automatically while Rectangle doesn't so Layout.fillHeight is not working as you wanted.

One sulotion would be to determine the size by the parent, I.e:

import QtQuick 2.4
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12

Rectangle{
    anchors.fill: parent;

    color: "grey"
    ColumnLayout{
        anchors.fill: parent
        anchors.topMargin: 10
        anchors.bottomMargin: 10
        anchors.rightMargin: 10
        anchors.leftMargin: 10
        spacing: 10

        Rectangle{
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "#600000"
            implicitHeight: parent.height / 3
        }

        Button{

            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "Button1"
            implicitHeight: parent.height / 3
        }

        Button{
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "Button2"
            implicitHeight: parent.height / 3
        }
    }
}

Another would be to override the implicitHeight property of Button like this:

import QtQuick 2.4
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12

Rectangle {
    anchors.fill: parent;

    color: "grey"
    ColumnLayout{
        anchors.fill: parent
        anchors.topMargin: 10
        anchors.bottomMargin: 10
        anchors.rightMargin: 10
        anchors.leftMargin: 10
        spacing: 10

        Rectangle{
            id: rect1
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "#600000"
        }

        Button{
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "Button1"
            implicitHeight: rect1.implicitHeight
        }

        Button{
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "Button2"
            implicitHeight: rect1.implicitHeight
        }
    }
}

Like mentioned by @ניר the issue is that the Buttons have an implicitHeight set. If a ColumnLayout has multiple children with Layout.fillHeight set to true, it will use their implicitHeight or Layout.preferredHeight as a "weight" to distribute the remaining height (see QtQuick Layouts Overview: Size Constraints). In your case you can do what you want by setting a fixed preferredHeight for all the children, no need to reference the parent or one of the siblings:

    Rectangle {
        anchors.fill: parent
        color: "grey"
        ColumnLayout {
            anchors.fill: parent
            anchors.margins: 10
            spacing: 10

            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredHeight: 1
                color : "#600000"
            }
            Button {
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredHeight: 1
                text: "Button1"
            }
            Button {
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredHeight: 1
                text: "Button2"
            }
        }
    }
Related