KernelPanic
KernelPanic

Reputation: 2432

Items not correctly spread across GridLayout

I have the following custom QML Item, which will represent a pin code entry GUI element:

import QtQuick 2.0
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.3

import "../items"

Item
{
    id: ueKeypad

    width: 512
    height: 512

    Rectangle
    {
        id: ueKeypadWrapper
        antialiasing: true

        anchors.fill: parent

        ColumnLayout
        {
            id: ueKeypadLayoutMain
            antialiasing: true

            layoutDirection: Qt.LeftToRight
            spacing: 8

            anchors.fill: parent

            ColumnLayout
            {
                id: ueKeypadTitleLayout

                layoutDirection: Qt.LeftToRight

                Layout.fillWidth: true

                Layout.minimumHeight: 24
                Layout.preferredHeight: 24
                Layout.maximumHeight: 24

                Text
                {
                    Layout.fillWidth: true
                    Layout.fillHeight: true

                    text: qsTr("PIN ENTRY")
                    clip: true
                    font.bold: true
                    font.pointSize: 24
                    textFormat: Text.RichText
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                }   // Text
            }   // ColumnLayout

            GridLayout
            {
                id: ueKeypadNumbersLayout

                Layout.fillWidth: true
                Layout.fillHeight: true

                Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter

                layoutDirection: Qt.LeftToRight

                columnSpacing: 8
                rowSpacing: 8

                flow: GridLayout.LeftToRight

                columns: 3

                UeButton
                {
                    id: ueKeypadButton1

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("1")
                }

                UeButton
                {
                    id: ueKeypadButton2

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("2")
                }

                UeButton
                {
                    id: ueKeypadButton3

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("3")
                }

                UeButton
                {
                    id: ueKeypadButton4

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("4")
                }

                UeButton
                {
                    id: ueKeypadButton5

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("5")
                }

                UeButton
                {
                    id: ueKeypadButton6

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("6")
                }

                UeButton
                {
                    id: ueKeypadButton7

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("7")
                }

                UeButton
                {
                    id: ueKeypadButton8

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("8")
                }

                UeButton
                {
                    id: ueKeypadButton9

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32

                    ueText: qsTr("9")
                }
            }   // GridLayout

            RowLayout
            {
                id: ueKeypadActionLayout

                Layout.fillWidth: true
                Layout.fillHeight: true

                Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter

                layoutDirection: Qt.LeftToRight

                spacing: 8

                UeButton
                {
                    id: ueKeypadButtonOk

                    ueText: qsTr("Ok")
                }   // UeButton

                UeButton
                {
                    id: ueKeypadButton0

                    ueText: qsTr("0")

                    Layout.minimumHeight: 32
                    Layout.preferredHeight: 32
                    Layout.maximumHeight: 32
                }   // UeButton

                UeButton
                {
                    id: ueKeypadButtonCancel

                    ueText: qsTr("Cancel")
                }   // UeButton
            }   // RowLayout
        }   // ColumnLayout
    }   // Rectangle
}   // Item

It uses custom QML Button, named UeButton:

import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick 2.5

Button
{
    property string ueText

    id: ueButton

    text: ueText

    style: ButtonStyle
    {
        background: Rectangle
        {
            antialiasing: true
            smooth: true
            gradient: Gradient
            {
                GradientStop
                {
                    position: 0
                    color: "#ffffff"
                }   // GradientStop

                GradientStop
                {
                    position: 0.418
                    color: "#000000"
                }   // GradientStop
            }   // Gradient

            border.color: "steelblue"
            border.width: control.activeFocus?2:1
            radius: 4
        }   // background

        label: Text
        {
            color: "#ffffff"
            font.bold: true
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: 16

            text: control.text
        }   // label
    }   // ButtonStyle
}   // ueButton

If I view first code in QtCreator's Designer Tool, I get the following situation:

Problem Screenshot

Why are Buttons not spread across GridLayout? Same goes to lower RowLayout, whose Items (three Items of type UeButton) are not centered and aligned across whole RowLayout?

Upvotes: 2

Views: 4431

Answers (1)

BaCaRoZzo
BaCaRoZzo

Reputation: 7682

The attached properties of a Layout ensures that the Items contained are correctly sized w.r.t. the given constraints.

Items can be stretched to fill the available space (fillWidth/fillHeight), forced to not shrink under a certain value (minimumWidth/minimumHeight) or not enlarge over a certain other value (maximumWidth/maximumHeight). You can also force an Item to occupy more than one row/column (rowSpan/columnSpan) and to assume a specific size (preferredWidth/preferredHeight which implies minimum == maximum).

The precedence is:

preferred <minimum/maximum < width/height

Setting a property to the left automatically discard any to the right. You can easily understand the reasoning behind this. This scheme can be somewhat "broken" by implicitWidth/implicitHeight since the size of any Item cannot shrink under these values. fill properties ensure that the Item fills the available space, according to the constrains above: if fill is not defined an Item cannot grow or shrink according to its constrains.

Now, if you want the Buttons to maintain they aspect and still stretch the grid, you can use an intermediate Item. While applying Layout attached properties to the external Item, the Buttons can be centerIn it and be unaffected.

Sample code:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    width: 200; height: 200; minimumHeight: 100; visible: true

    GridLayout {
        anchors.fill: parent
        rows: 3
        columns: 3

        Repeater {
            model: 9

            Item {
                Layout.fillWidth: true
                Layout.fillHeight: true

                Button { anchors.centerIn: parent; width: 32; height: 32; text: index + 1 }
            }
        }
    }
}

Instead if you want the Buttons to fill the available space, just specify fillWidth/fillHeight. Since no other layout constraints are set (e.g. minimum*, maximum*) the Buttons correctly occupy all the available space. Here is the code above revisited. As expected, width and height are simply discarded:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    width: 200; height: 200; minimumHeight: 100; visible: true

    GridLayout {
        anchors.fill: parent
        rows: 3
        columns: 3

        Repeater {
            model: 9

            Button {width: 32; height: 32; text: index + 1;   // 32? NOPE!
                Layout.fillWidth: true; Layout.fillHeight: true
            }
        }
    }
}

Upvotes: 4

Related Questions