Search code examples
qtlayoutqmlqtquick2

In QML, how to set properties for every child of a Layout?


I'm new to QML and I want to place a bunch of itmes in a column. Lets say I have a custom component called MyComponent which is basically a rounded Rectangle with text in it.

I want to put e.g. 5 of those MyComponent elements in a column like this:

ColumnLayout {
    MyComponent { text: "a" }
    MyComponent { text: "b" }
    MyComponent { text: "c" }
    MyComponent { text: "d" }
    MyComponent { text: "e" }
}

I cannot use a Repeater as each element should have a different text. Now, let's say I want to stretch these elements horizontally. In a ColumnLayout, i guess you have to do it like this:

ColumnLayout {
    MyComponent {
        text: "some text"
        Layout.fillWidth: true
    }
}

But this means I'd have to do this manually for every single MyComponent, as setting Layout.fillWidth: true for the ColumnLayout does not work. So how can I set something like the default layout for child elements? How can I just say that every element in the ColumnLayout should be stretched horizontally?

(and, btw, is there any reason why in QML child elements position themselves inside their parent elements, and not vice-versa? Like, in CSS, when I have a flex column, I configure the basic positioning inside the flex container, not the flex items. Like, when I want every item to be stretched horizontally, I could just say align-items: center. And to me this approach makes a lot more sense because it follows the layout hierarchy - the container is one level above the child, so it controls how to position the child, not the other way. But that might also be just my subjective opinion)


Solution

  • This statement

    I cannot use a Repeater as each element should have a different text

    is incorrect, since, as Soheil Armin points out, the different text can be put in the model of the Repeater (either a JS array or a ListModel will work). As to declaring a style where Layout.fillWidth: true is applied to MyComponent, we can do that with a derivative component, say, MyComponent2, e.g.

    ColumnLayout {
        Repeater {
            model: ["a","b","c","d","e"]
            delegate: MyComponent2 { text: modelData }
        }
    }
    
    // MyComponent2.qml
    import QtQuick.Layouts
    MyComponent {
         Layout.fillWidth: true
    }
    
    // MyComponent.qml
    import QtQuick
    import QtQuick.Controls
    import QtQuick.Layouts
    Label {
        Layout.margins: 10
        background: Item {
            Rectangle {
                anchors.fill: parent
                anchors.margins: -8
                radius: 10
                border.color: "black"
           }
        }
    }
    

    You can Try it Online!

    As to your subsequent point about element types, that isn't demonstrated in your question, but, if it were, it is covered by @smr's comment about DelegateChooser.