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 settingrows
andcolumns
. The only purpose ofrows
orcolumns
is to tell the layout engine when to wrap to the next column or row when auto-assigning row and column numbers. TheGridLayout
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
andfillHeight
set to "inflate" those rows and columns to the desired size. You can do that by filling unused positions with dummyItem
objects that have the necessaryLayout
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
, orRectangle
if you want a background color. ItsComponent.onCompleted
handler can iterate through its children and set the position and size of its children based on theirLayout.column
andLayout row
properties, along withspacing
andmargins
properties on your object. You could even supportLayout.columnSpan
andLayout rowSpan
with some simple arithmetic. -
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 } } }
-
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 } } }
-
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 } } }
@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.
-
@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.qmlGridLayout{ 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 } }
-
@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.qmlGridLayout{ 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?