GridLayout with equal sized cells



  • Hi all,

    is there a way to force a GridLayout to keep the cells equally sized so I can use it as a real layout grid?
    Example:

    GridLayout {
      width: 100
      height: 100
      columns: 5
      rows: 5
      columnSpacing: 0
      rowSpacing: 0
      Rectangle {
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.column: 2
        Layout.row: 1
      }
    }
    

    The rectangle in the example should sit at x = 40 and y = 20 and the size should be 20x20.



  • I know this is old, but someone might find this useful.

    You don't set the size of a GridLayout by setting rows and columns. The only purpose of rows or columns is to tell the layout engine when to wrap to the next column or row when auto-assigning row and column numbers. The GridLayout ultimately derives its size from the highest numbered row and column occupied.

    Furthermore, you have to actually put something into every row and column that has its fillWidth and fillHeight set to "inflate" those rows and columns to the desired size. You can do that by filling unused positions with dummy Item objects that have the necessary Layout properties. In fact, you only need to ensure that at least one position in each row and column is so occupied in order to force the layout.

    It's pretty easy to write your own fixed grid object in QML, derived from Item, or Rectangle if you want a background color. Its Component.onCompleted handler can iterate through its children and set the position and size of its children based on their Layout.column and Layout row properties, along with spacing and margins properties on your object. You could even support Layout.columnSpan and Layout rowSpan with some simple arithmetic.



  • I was trying to avoid the things you supposed to get GridLayout to do what I want. In the end I did what you supposed in your last paragraph, I wrote my own TableLayout component.



  • GridLayout{
        property bool showGridLines : true
        implicitHeight: 150
        implicitWidth: 150
        rowSpacing: 0
        columnSpacing: 0
        id:gridlayout
        Repeater{
            id:repeater
            model: gridlayout.rows*gridlayout.columns
            delegate:Rectangle{
                property var i : parseInt(index / gridlayout.rows)
                property var j : index % gridlayout.columns
                Layout.fillWidth:true
                Layout.fillHeight:true
                Layout.row: i
                Layout.column: j
                color:"transparent"
                border.width: showGridLines?1:0
            }
        }
    }
    

    0_1557478172939_dddss.PNG



  • @haftado3 What do you wanna show with your example?



  • @haftado3 I think i needs gridlayout.columns in the denominator. It worked here because the number of rows and columns happened to be the same. You also don't need i and j, since you could just define Layout.row and Layout.column with the expressions. And you wouldn't need parseInt because the properties truncate to integers anyway. Finally, I think you could just use Item for the delegate, since that's pretty much the same thing as a transparent Rectangle.

    But anyway, don't you see lots of warnings in the log, when you place real items (like the small images) in the same cells as the repeated rectangles? That's a problem I've hoped to find a workaround for.



  • @pderocco first, item do not have border i guess , so i used transparent rectangle, i used parseInt to round down devide value, i created rectangle here to set fixed size for Grid columns and rows ,i and j was for debugging reasons and removed:
    FixGrid.qml

    GridLayout{
        default property list<Item> childrens
        Component.onCompleted: {
            if(childrens != null){
                for(var z = 0;z<childrens.length;++z){
                    var row = childrens[z].Layout.row
                    var col = childrens[z].Layout.column
                    var result = (row+1)*(col+1)
                    childrens[z].parent = gridlayout.children[result]
                }
            }
        }
    
        property bool showGridLines : false
        implicitHeight: 150
        implicitWidth: 150
        rowSpacing: 0
        columnSpacing: 0
        id:gridlayout
        Repeater{
            id:repeater
            model: gridlayout.rows*gridlayout.columns
            delegate:Rectangle{
                clip: true
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.row: parseInt(index / gridlayout.rows)
                Layout.column: index % gridlayout.columns
                color:"transparent"
                border.width: showGridLines?1:0
    
            }
        }
    }
    

    this will work but some changes will be needed :

    FixGrid{
            columns : 5
            rows : 6
            Button{
                  Layout.column : 2
                  Layout.row : 0
            }
    }
    


  • @haftado3 Again, what do you want to show with your example? What is your "childrens" property good for? I think it doesn't solve the issue I had when I started the thread.

    BTW: Using "parseInt" to round down a number value is not really performant. It converts your floating point value to a string and parses it. It's by far faster to use Math.floor. But I think in this case, "Layout.row" is an integer property, so you don't need to convert it explicitly, it's done implicitly when you assign a floating point value to it.

    But again, is your code solving the issue the original post was about?


Log in to reply