How to set a background for a qml item of unspecified size?

qml
16,637

First of all, if you want your container to have a background, you have to make Rectangle the root instead of placing Rectangle inside Item. Also, you cannot use anchors inside a Layout since a Layout manages the layout of its children according to its own rules.

As for the question, you can use a Layout since it grows to contains all its children, like in the code as below:

Rectangle {
    anchors.centerIn: parent
    width: grid.width + 10
    height: grid.height + 10
    color: "orange"
    GridLayout {
        anchors.centerIn: parent
        id: grid
        columns: 5
        rowSpacing: 2
        columnSpacing: 2
        Repeater {
            model: 10 + Math.round(Math.random() * 50)
            Rectangle {
                width: 20 + Math.round(Math.random() * 50)
                height: 20 + Math.round(Math.random() * 50)
                border.width: 1
                border.color: "#999"
            }
        }
    }
}

Another solution is to use Item.childrenRect:

Rectangle {
    id: container
    anchors.centerIn: parent
    width: childrenRect.x + childrenRect.width;
    height: childrenRect.y + childrenRect.height;
    border.width: 1
    border.color: "#999"
    Repeater {
        model: 10 + Math.round(Math.random() * 50)
        Rectangle {
            x: Math.round(Math.random() * 500)
            y: Math.round(Math.random() * 500)
            width: 100 + Math.round(Math.random() * 100)
            height: 100 + Math.round(Math.random() * 100)
            color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)
        }
    }
}
Share:
16,637
vsz
Author by

vsz

Updated on June 14, 2022

Comments

  • vsz
    vsz about 2 years

    The simplest way to set a background to a qml item is to just have a child rectangle whose anchors completely fill up the parent:

    Item
    {
        width: 320
        height: 240
        Rectangle
        {
            id: background
            anchors.fill: parent
            color: "blue"
        }
    
        // other items
    
    }
    

    However, this only works it the parent item has a size (width and height) defined.

    I would like to have a container without defining a fixed size for it. The children will have fixed sizes, but as the children can change their sizes dynamically, I would like for the parent container to grow and shrink to fit.

    If I anchor the children in a sequence, everything works well except for the background.

    There was a question a while ago about a similar topic, but there the issue was that all the children were overlapping instead of displayed side by side. That is not my problem, because anchoring them in a sequence (or using a RowLayout) displays them correctly.

    Item
    {
        // I don't want a fixed size here
    
        Rectangle
        {
            id: background
            anchors.fill: parent
            color: "blue"
        }
    
    
        RowLayout
        {
            anchors.fill: parent
    
            Item
            {
                id: child1
                anchors.left = parent.left
                anchors.top: parent.top
    
                width:100
                height:100
            }
    
            Item
            {
                id: child2
                anchors.left = child1.right
                anchors.top: parent.top
    
                width:120
                height:120
            }
    
            // further children
    
        }
    
    }
    

    However, the background is not displayed because the parent doesn't have a defined size, although all the children do have a fixed size, and if I specify the right anchor of the last child to be the right of the parent, it is still displayed correctly. I guess this means that the size of the parent should be known by the renderer.

    (If I use an Item or a Rectangle instead of the RowLayout, nothing changes. Actually, when using a RowLayout I could omit the sequential anchoring, but this doesn't change my problem with the background)