How to make QML items to grow to fit contents?

51,977

Solution 1

You must give a size to containers, and add anchors / bindings in children :

main.qml :

import QtQuick 1.1
import "Teeworlds" as Teeworlds

Item {
    width: 800; // root item so give a size
    height: 600;

    Flickable {
         clip: true;
         anchors.fill: parent; // use a flickable to allow scrolling
         contentWidth: width; // flickable content width is its own width, scroll only vertically
         contentHeight: layout.height; // content height is the height of the layout of items

         Column {
             id: layout;
             anchors { // the column should have a real size so make it fill the parent horizontally
                 left: parent.left;
                 right: parent.right;
             }

             Teeworlds.ServerItem {
                serverName: "InstaGib, lost [xyz]";
             }
             Teeworlds.ServerItem {
                serverName: "Arena.sbor (rus)";
             }
        }
    }
 }

Teeworlds/ServerItem.qml :

import QtQuick 1.1

BorderImage {
    id: serverItem;
    height: grid.y + grid.height; // compute the item height using content position and size
    anchors { // to have a real size, items should grow horizontally in their parent
        left: parent.left;
        right: parent.right;
    }

    property string serverName  : "unnamed server";
    property string gameType    : "DM";
    property int      numPlayers  : 0;
    property int      maxPlayers   : 8;
    property int      ping               : 60;

    Text {
        id: title;
        text: parent.serverName;
    }
    Grid {
        id: grid;
        columns: 2;
        anchors { // the grid must anchor under the title but horizontally in the parent too
            top: title.bottom;
            left: parent.left;
            right: parent.right;
        }

        Text { text: "Gametype: " } 
        Text { text: gameType }
        Text { text: "Players: " }  
        Text { text: numPlayers + "/" + maxPlayers }
        Text { text: "Ping: " }    
        Text { text: ping }
    }
}

Remember that by default all Item, Rectangle, BorderImage have no size,no position, and that Column, Row, Flow, Grid, Text and Image size themself to their content, so if you want to use the Column to resize its children you must ensure that column size is no more automatically defined by the one of its children. Because elsewhere, the children will stay 0x0 and column will also be 0x0. Column should be anchored into its parent to have a real size, and its children should anchor horizontally (left and right) into column to have a real width, and for the height items must size them self according to their internal layout...

Solution 2

Actually that's quite easy. The ServerItem objects have no size, you can only see the content because there is no clipping. The solution would be either to set height and width in the ServerItem class (or the instances in main.qml) or to use a growing element, e.g. a Column, as the ServerItem root element.

import QtQuick 1.0

Column {
    id: serverItem

    BorderImage {
        anchors.fill: parent
    }

    //... the rest
}

Solution 3

You have to set a size explicitly so that two QML elements inside a Row/Column doesn't overlap.

Share:
51,977
lamefun
Author by

lamefun

Updated on June 26, 2020

Comments

  • lamefun
    lamefun about 4 years

    How to make ServerItem to grow to fit contents? Right now ServerItems just overlap each other.

    main.qml

    import Qt 4.7
    import "Teeworlds" as Teeworlds
    
    Item {
        Column {
            Teeworlds.ServerItem {
                serverName: "InstaGib, lost [xyz]"
            }
    
            Teeworlds.ServerItem {
                serverName: "Arena.sbor (rus)"
            }
        }
    }
    

    ServerItem.qml

    import QtQuick 1.0
    
    BorderImage {
        id: serverItem
    
        property string serverName: "unnamed server"
        property string gameType: "DM"
        property int numPlayers: 0
        property int maxPlayers: 8
        property int ping: 60
    
        Text {
            id: title
            text: parent.serverName
        }
    
        Grid {
            id: grid
            anchors.top: title.bottom
            columns: 2
            rows: 3
            Text { text: "Gametype: " }  Text { text: gameType }
            Text { text: "Players: " }   Text { text: numPlayers + "/" + maxPlayers }
            Text { text: "Ping: " }      Text { text: ping }
        }
    }