Search code examples
qtqmlqtquick2

QtQuick - what is meant by "parent item"?


The following QML code:

Window {
    id: window

    width: 450
    height: 700
    visible: true

    StackView {
        id: mainStack

        property Item itemTest: Item {
            id: itemTest

            ColumnLayout {
                id: mainLayout

                width: mainStack.width

                ScrollView {
                    id: scrollview

                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    clip: true
                    ScrollBar.horizontal.policy: ScrollBar.AlwaysOff

                    ColumnLayout{
                        id: colLayout
                        anchors.fill: scrollview
                    }
                }
            }
        }
        initialItem: itemTest
        anchors.fill: parent
    }
}

gives an error of "QML ColumnLayout: Cannot anchor to an item that isn't a parent or sibling."

Replacing anchors.fill: scrollview by anchors.fill: parent makes this message disappear but then the ColumnLayout does not seem to fill the ScrollView.

Given this behaviour, I've come to the conclusion that the scrollView in this QML file isn't actually the parent of colLayout, which goes against my first intuition about the way parenting works in QML.

Can someone explain to me what is meant exactly by the keyword "parent" in QML? Many thanks in advance.


Solution

  • The issue is that Controls use the concept of a contentItem. While the ScrollView itself is a Control which itself is in turn an Item, the children are parented to a different Item called contentItem.

    More info here:

    https://doc.qt.io/qt-5/qml-qtquick-controls2-control.html#contentItem-prop

    See also the comment there:

    Note: Most controls use the implicit size of the content item to calculate the implicit size of the control itself. If you replace the content item with a custom one, you should also consider providing a sensible implicit size for it (unless it is an item like Text which has its own implicit size).

    You don't want to grow your ColumnLayout to match the contentItem, the contentItem will automatically resize to fit the implicit size of the ColumnLayout.

    If the effect you are trying to get is to match the size of the ColumnLayout to that of the ScrollView, then use something like:

                        ColumnLayout{
                            id: colLayout
                            implicitWidth: scrollview.width
                            implicitHeight: scrollview.height
                            height: implicitHeight
                            width: implicitWidth
                        }
    

    But in that case, why bother using a ScrollView? Normally you would allow the ColumnLayout to manage its implicit size normally based on it's children. When the contentItem ends up overflowing the ScrollView, then it starts to automatically scroll.