ColumnLayout sizing policy and TableView maximum height limitation problem
-
Question about
ColumnLayout
and its sizing policy. I have several nested components withColumn
s (ColumnLayout
) in my design. I want to organize UI to be resizable to restrictTableView
height to fit within the app window. In other words, I want it to be anchored to the bottom of the main window (taking margins into account of course), but only if when there are a lot of rows, or ifTableView
is content is small, then it should not be anchored it to app window bottom.The container
Rectangle { id: frame }
should be also anchored to the window bottom only ifTableView
is too big.Previously I had design with
Column
s, then converted them toColumnLayout
with spacerItem
added at main window bottom. Logic in code below works mostly fine, however have small issues I want to resolve:- if
tableFillHeight
property is true - everything looks fine and works as expected; - if
tableFillHeight
is false thentableView
become too big (overlapsRectangle { id: frame }
so there is no bottom margin which is specified byframeColumn
margins property, andtotalRecordsText
drawn below (overlaps)Rectangle {id: frame}
too, while it should be inside it - so I assumeLayout
logic some kind broken or incomplete there.
Could you please help me understand what might be wrong? Where did I miss something about the layout logic? Thanks!
ApplicationWindow { // top component property alias tableFillHeight: frame._fillHeight ColumnLayout { id: mainLayout anchors.fill: parent anchors.margins: defaultPixelHeight * 4 / 3 Text { id: appHeader Layout.topMargin: defaultPixelHeight * 4 / 3 Layout.fillWidth: true } Rectangle { // separate nested component id: frame Layout.fillWidth: true Layout.fillHeight: _fillHeight readonly property bool _fillHeight: { let bottomInMain = mapToItem(applicationWindow.contentItem, 0, implicitHeight).y return bottomInMain > (applicationWindow.height - mainLayout.anchors.margins) } implicitHeight: frameColumn.implicitHeight ColumnLayout { id: frameColumn anchors.fill: parent anchors.margins: defaultPixelHeight * 4 / 3 spacing: defaultPixelHeight Row { Text {} } Rectangle { id: serviceFrame Layout.fillWidth: true } ColumnLayout { // separate nested component Layout.fillWidth: true Layout.fillHeight: tableFillHeight spacing: defaultPixelHeight Row { Button {} } ColumnLayout { // separate nested component id: tableColumn Layout.fillWidth: true Layout.fillHeight: tableFillHeight implicitHeight: tableFillHeight ? -1 : tableColumn.implicitHeight spacing: 2 HorizontalHeaderView { id: header Layout.fillWidth: true syncView: tableView } TableView { id: tableView Layout.fillWidth: true Layout.fillHeight: tableFillHeight implicitHeight: contentItem.height } } Text { id: totalRecordsText text: qsTr("Total — ") + records_count.toString() } } } } Item { id: spacer Layout.fillWidth: true Layout.fillHeight: !tableFillHeight visible: !tableFillHeight } } }
Summarizing:
✅
TableView
(with its containingRectangle
) should expand and fill remaining space only when its content is large.
✅ It should shrink when content is small.
✅ It must stay inside the Rectangle (frame) and not overflow.
✅totalRecordsText
must stay visible insideframe
as well and not overlap. - if
-
Solution was mostly there and fix appeared very simple:
- move anchors margins from
_fillHeight
property calculations to
readonly property bool _fillHeight: { let bottom = mapToItem(applicationWindow.contentItem, 0, implicitHeight).y; return bottom > applicationWindow.height }
frame.implicitHeight
property:
implicitHeight: frameColumn.implicitHeight + defaultPixelHeight * 4
Now everything works and looks fine! No errors or binding loops.
- move anchors margins from
-
A Aleksey_K has marked this topic as solved