Padding
You attach elements to left and right edges of the column,
but then tell the column it should position its elements 10 pixels away from that border.
They then start to "fight" each other by each causing layout update and thus triggering each other.
You need to place an intermediate element to handle padding like that:
Column{ padding: 10; Column{ id: col; Rectangle{}; Rectangle{}; } }
Anchors
Let's see what's actually happening
I inserted some debugging code in each element:
property string name: "..."//I named them: "green_rect", "blue_rect", "col", "top_rect", "bottom_rect"
onWidthChanged: console.log(name + " changed: w=" + width)
....
property string mydbgstr: "top_rect w=" + width + " h=" + height + " iw=" + implicitWidth + " ih=" + implicitHeight
onMydbgstrChanged: console.log(mydbgstr)
It prints a string when any of the properties changes
My window is 500x500
Initial layout - this remains the same for all cases:
// property change notifications removed since they are not interesting yet
qml: bottom_rect w=200 h=25 iw=200 ih=25
qml: top_rect w=100 h=25 iw=100 ih=25
qml: col w=0 h=0 iw=0 ih=0
qml: blue_rect w=0 h=0 iw=0 ih=0
qml: green_rect w=0 h=0 iw=0 ih=0
okay so anchors are not applied yet, and the column hasn't calculated its size yet, so elements simply assume h=ih w=iw
After that we see different conclusions:
Both top and bottom rectangles' anchors commented:
qml: col changed: w=200
qml: col changed: h=60
qml: col changed: iw=200
qml: blue_rect changed: w=200
qml: blue_rect changed: iw=200
qml: blue_rect w=200 h=0 iw=200 ih=0
qml: col changed: ih=60
qml: col w=200 h=60 iw=200 ih=60
qml: blue_rect changed: h=60
qml: blue_rect changed: ih=60
qml: blue_rect w=200 h=60 iw=200 ih=60
qml: green_rect changed: w=500
qml: green_rect w=500 h=500 iw=0 ih=0
qml: green_rect changed: h=500
Result:
▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀
Works as expected: column calculates its size based on combined children sizes,
then surrounding element also assumes that size
Only top rect's anchors uncommented:
// it appears that top rect adjusted itself to fit still-zero-width column
qml: top_rect changed: w=0 col.w=0 //uh oh, top_rect is now zero-sized
qml: top_rect w=0 h=25 iw=100 ih=25
// here col probably performed layout and determined its width based on bottom rect
// however for some reason its own signal got delayed (isn't shown)
// probably because children get priority
// top_rect anchors react to column layout:
qml: top_rect changed: w=200 col.w=200 //top_rect is properly sized again
qml: top_rect w=200 h=25 iw=100 ih=25
// here col appears to react to the first layout change:
qml: col changed: w=200
qml: col changed: h=25 // height excludes top_rect which was zero-size at that point
qml: col changed: iw=200 // bottom_rect retained its size so col isn't zero-sized
//...and so surrounding elements are updated
qml: blue_rect changed: w=200
qml: blue_rect changed: iw=200
qml: blue_rect w=200 h=0 iw=200 ih=0
//...next col decides to update its implicitHeight
qml: col changed: ih=25
qml: col w=200 h=25 iw=200 ih=25
//...which causes a second layout of surroundings:
qml: blue_rect changed: h=25
qml: blue_rect changed: ih=25
qml: blue_rect w=200 h=25 iw=200 ih=25
qml: green_rect changed: w=500
qml: green_rect changed: h=500
qml: green_rect w=500 h=500 iw=0 ih=0
//This is apparently col getting the second update of top_rect:
qml: col changed: h=60 //height now includes non-zero-sized top_rect
qml: col changed: ih=60
qml: col w=200 h=60 iw=200 ih=60
//...so blue_rect is changed yet again:
qml: blue_rect changed: h=60
qml: blue_rect changed: ih=60
qml: blue_rect w=200 h=60 iw=200 ih=60
Result:
▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀
Both uncommented:
// col is zero-sized still so children cling to its zero-size
qml: bottom_rect changed: w=0 col.w=0
qml: bottom_rect w=0 h=26 iw=200 ih=26
qml: top_rect changed: w=0 col.w=0
qml: top_rect w=0 h=24 iw=100 ih=24
// because all children are zero-sized, col is also zero-sized so it doesn't attempt to do anything
// because col is zero-sized, blue_rect also remains zero-sized
qml: green_rect changed: w=500
qml: green_rect changed: h=500
qml: green_rect w=500 h=500 iw=0 ih=0
Result: green window
Conclusion
Column width depends on largest element width but element width is anchored to column so it has a chicken-and-egg-problem but since it's indirect and also causes initial zero size to persist, Qt cannot detect a binding loop and instead the elements remain collapsed.
This effectively means that QtQuick is not "smart" enough to properly position items in this case. You have to either specify actual width for one of the items or the column.
ColumnLayout
is a bit smarter in that it can have minimum, maximum and preferred sizes specified so you should probably use it instead of Column
. I understand you already figured out how to use it so I won't go into details here.
Alternatively, imperative code could be used to determine largest of the elements' width and set col's width to that. It can also set other elements' width if desired.
ColumnLayout
work any better for you? – JarMan