Search code examples
qtqmlqtquick2

Trouble centre-aligning items within a QtQuick StackLayout


I'm having trouble centre-aligning items within a QtQuick StackLayout using qml. As far as I can see I'm doing things correctly according to the docs, but I can't get the behaviour I'm after. Any help would be greatly appreciated.

I'd like to use a stack layout such that when the item at the current index is smaller than the minimum size of the layout, it is not stretched but positioned in the centre of the layout. I understand the mechanism for this is the Layout.alignment attached property which I set to Qt.AlignHCenter | Qt.AlignVCenter on the item, however this seems to have no effect. The item remains in the top left corner.

I also need the stack layout to have an implicit size of the Item at the current index, rather than the maximum size of all the items. This I think I have achieved by overriding the implicit size properties.

I've got a minimal reproduction of my issue in the snippet bellow. The red Rectangle should be centred within the StackLayout, however it is positioned in the top left corner. You can paste this into qmlonline.kde.org to get a quick render of the scene.

import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15

ColumnLayout {
    StackLayout {
        id: stack
        
        currentIndex: 0
        implicitWidth: children[currentIndex].implicitWidth
        implicitHeight: children[currentIndex].implicitHeight
        
        Layout.minimumWidth: 400
        Layout.minimumHeight: 250
        Layout.fillWidth: true
        Layout.fillHeight: true
        
        Rectangle {
            color: "red"
            implicitWidth: 100
            implicitHeight: 100
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
            Layout.fillHeight: false
            Layout.fillWidth: false
        }
                    
        Rectangle {
            color: "green"
            implicitWidth: 500
            implicitHeight: 300
            Layout.fillHeight: false
            Layout.fillWidth: false
        }
    }
    RowLayout {
        Button {
            text: "Red"
            onClicked: stack.currentIndex = 0
        }
        Button {
            text: "Green"
            onClicked: stack.currentIndex = 1
        }
    }
}

Solution

  • understand the mechanism for this is the Layout.alignment attached property which I set to Qt.AlignHCenter | Qt.AlignVCenter on the item, however this seems to have no effect. The item remains in the top left corner.

    StackLayout does not support Layout.alignment attached property... The list of supported properties is explicitly listed in the documentation.

    Simply wrap your rectangle inside an Item, which will occupy all space inside StackLayout by default and center Rectangle in it.

            Item {
                Rectangle {
                    anchors.centerIn: parent
                
                    color: "red"
                    implicitWidth: 100
                    implicitHeight: 100
                }
            }
    

    I also need the stack layout to have an implicit size of the Item at the current index, rather than the maximum size of all the items. This I think I have achieved by overriding the implicit size properties.

    Yes, so simply bind wrapping Item implicit sizes to match wrapped Rectangle

            Item {
                implicitWidth: rect.implicitWidth
                implicitHeight: rect.implicitHeight
            
                Rectangle {
                    id: rect
                
                    anchors.centerIn: parent
                
                    color: "red"
                    implicitWidth: 100
                    implicitHeight: 100
                }
            }
    

    Demo