How to give specific spacing to items in a QML layout?

11,870

Solution 1

Differently from previous positioners, such as Column or Row, layouts were introduced to support graphical scaling of UI, also by filling available space (in this specific case fill their parent). In that sense the spacing property should not be seen as a strict upper bound to the spacing between Items but as the minimum allowed distance between them.

The current approach to solve your issue is to use a "filler" Item, which uses the fillHeight property. This Item occupies all the space left by the other Items inside the layout thus packing them together, as needed:

import QtQuick 2.5
import QtQuick.Window 2.2

Window {
    visible: true

    width: 100
    height: 200

    ColumnLayout {
        anchors.fill: parent
        spacing: 2

        Rectangle {
            height: 50
            width: 50
            color: "red"
        }
        Rectangle {
            height: 50
            width: 50
            color: "green"
        }
        Rectangle {
            height: 50
            width: 50
            color: "blue"
        }
        Item { Layout.fillHeight: true }    // <-- filler here
    }
}

Note that you can exploit the same approach and add a filler at the beginning of the layout to vertically center the children Items. Finally, note that in this case it would be advisable to use a Column which lays down the Items correctly as expected, disregarding the available space left.

Just make your choice.


It should be noted that while this approach works Layouts provide a lot of properties to control the size of the Items. Please refer to the other answer for some insight on the subject.

Solution 2

The accepted answer is one valid approach, however, there are others.

1) ColumnLayout decides its own height

If you are simply trying to place items in a column from the top downwards, then there is no need to force the height of the ColumnLayout.

Instead of anchors.fill: parent use width: parent.width

and let the ColumnLayout size itself to fit its contents, as below:

import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    visible: true

    width: 100
    height: 200

    ColumnLayout {
        width: parent.width
        spacing: 2

        Rectangle {
            height: 50
            width: 50
            color: "red"
        }
        Rectangle {
            height: 50
            width: 50
            color: "green"
        }
        Rectangle {
            height: 50
            width: 50
            color: "blue"
        }
    }
}

2) ColumnLayout resizes the items to achieve desired spacing.

If there are too many or too few items to perfectly fill the layout, you can allow the layout to resize the items (instead of resizing the spacing).

The following attached properties control how the layout treats your items, when deciding what can be stretched or shrunk in order to fit the layout:

  • Layout.preferredHeight
  • Layout.minimumHeight
  • Layout.maximumHeight
  • Layout.fillHeight

Example, where Rectangles are enlarged slightly to achieve the desired spacing:

import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    visible: true

    width: 100
    height: 200

    ColumnLayout {
        anchors.fill: parent
        spacing: 2

        Rectangle {
            Layout.fillHeight: true
            Layout.preferredHeight: 50
            width: 50
            color: "red"
        }
        Rectangle {
            Layout.fillHeight: true
            Layout.preferredHeight: 50
            width: 50
            color: "green"
        }
        Rectangle {
            Layout.fillHeight: true
            Layout.preferredHeight: 50
            width: 50
            color: "blue"
        }
    }
}
Share:
11,870
Silex
Author by

Silex

Updated on June 19, 2022

Comments

  • Silex
    Silex almost 2 years

    I have a ColumnLayout, which has its anchor set to anchor.fill: parent, therefore it has already a set dimension, which depends on its parent dimension.

    How can I add Rectangles into this ColumnLayout, with a specific spacing from top to bottom?

    Right now I have this:

    ColumnLayout {
      anchors.fill: parent
      spacing: 2
    
      Rectangle {
        height: 50
        width: 50
        color: "red"
      }
      Rectangle {
        height: 50
        width: 50
        color: "green"
      }
      Rectangle {
        height: 50
        width: 50
        color: "blue"
      }
    }
    

    But instead of having the rectangles from top to bottom with a spacing 2 it layouts the Rectangles evenly in the ColumnLayout.

    One solution would be to anchor the first rectangle to the parent's top and the anchor the rest of the rectangles one after the other, but I would like to avoid this if possible.