How to design a layered fluid layout in QML

I developed a layout in QML to learn more about its capabilities and ask some questions on “Best Practices” when developing such a layout. Here he is:

enter image description here

Essentially, a ColumnLayout consists of three RowLayout , each of which has several Rectangle . The size of each Row and Rectangle should be calculated as follows:

  • First line: Height = 40%, Width = 100%
    • A red rectangle filling the entire area.
  • Second line: Height = 20%, Width = 100%
    • Dark Green Rectangle: Height = 100%, Width = 20%,
    • Light green rectangle: height = 100%, width = 80%
  • Third row: Height = 40%, Width = 100%
    • Dark blue rectangle: height = 100%, width = 40%,
    • Blue Rectangle: Height = 100%, Width = 20%
    • Blue Rectangle: Height = 100%, Width = 40%

The QML I came across works and is in the following. I have some questions:

  • I set the width and height using the Layout.preferredHeight template : x * parent.height . Other options caused some problems (for example, preferredHeight caused binding loop warnings). Is my approach right and effective?
  • As a hack, I set Layout.fillWidth: true for the first element Row # 2 and Row # 3, which for me does not make sense, but it works. If I set their width as a percentage (e.g. Layout.preferredWidth: 0.2 * parent.width ), their string will decrease to a width of 0. Is this the expected behavior? Is there a better workaround?
  • Do you have any layout recommendations? Am I on the right track?

Here is my QML code for the layout:

ApplicationWindow { x: 500 y: 100 width: 250 height: 150 visible: true ColumnLayout { anchors.fill: parent spacing: 0 RowLayout { spacing: 0 Layout.preferredHeight: 0.4*parent.height Layout.fillHeight: false Rectangle { Layout.fillHeight: true Layout.fillWidth: true color: "red" } } RowLayout { spacing: 0 Layout.preferredHeight: 0.2*parent.height Layout.fillHeight: false Rectangle { Layout.fillHeight: true Layout.fillWidth: true color: "darkGreen" } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 0.8*parent.width color: "lightGreen" } } RowLayout { spacing: 0 Layout.preferredHeight: 0.4*parent.height Layout.fillHeight: false Rectangle { Layout.fillHeight: true Layout.fillWidth: true color: "darkBlue" } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 0.2*parent.width color: "blue" } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 0.4*parent.width color: "lightBlue" } } } } 

Update:

My approach seems more hacked than I expected:

  • Putting Text elements as children in this layout triggers binding loop warnings, such as:

QML QQuickLayoutAttached: Binding Cycle Detected for "preferredWidth" Property

If the carry text is inside the Rectangle , the warnings disappear.

  1. Value : 0 plays an important role. Omitting this will cause bind cycle warnings.

While my approach to fluid layout design in QML works, it has some serious issues and may not fall under the “best practices”.

+6
source share
2 answers

QtQuick.Layout provides no real improvement over the classic binding system. I would recommend avoiding them. You can have more control over the layout with anchors.

Here is the same design without QtQuick.Layout:

 ApplicationWindow { x: 500 y: 100 width: 250 height: 150 visible: true Column { anchors.fill: parent Row { anchors.left: parent.left anchors.right: parent.right height: 0.4 * parent.height Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: parent.width color: "red" } } Row { anchors.left: parent.left anchors.right: parent.right height: 0.2 * parent.height Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: 0.2 * parent.width color: "darkGreen" } Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: 0.8 * parent.width color: "lightGreen" } } Row { anchors.left: parent.left anchors.right: parent.right height: 0.4 * parent.height Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: 0.4 * parent.width color: "darkBlue" } Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: 0.2 * parent.width color: "blue" } Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom width: 0.4 * parent.width color: "lightBlue" } } } } 

So far I have never met a design that could not be bypassed without QtQuick.Layout.

+2
source

It is forbidden (and not necessary) to try to refer to the width and height of the parent element from the elements inside the layout.

If fillWidth (or fillHeight ) is set to true ), space is allocated to elements proportionally to the specified preferredWidth (or preferredHeight ).

Therefore, the correct way to create a layout is as follows. I changed the look only to show that distance and Text can also be set freely as desired. No bind cycles.

 ApplicationWindow { x: 500 y: 100 width: 250 height: 150 visible: true ColumnLayout { anchors.fill: parent spacing: 5 RowLayout { spacing: 5 Layout.preferredHeight: 40 Layout.fillHeight: true Rectangle { Layout.fillHeight: true Layout.fillWidth: true color: "red" } } RowLayout { spacing: 5 Layout.preferredHeight: 20 Layout.fillHeight: true Rectangle { Layout.fillHeight: true Layout.preferredWidth: 20 Layout.fillWidth: true color: "darkGreen" } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 80 Layout.fillWidth: true color: "lightGreen" } } RowLayout { spacing: 5 Layout.preferredHeight: 40 Layout.fillHeight: true Text { Layout.fillHeight: true Layout.preferredWidth: 40 Layout.fillWidth: true color: "darkBlue" text: "hello world!" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 20 Layout.fillWidth: true color: "blue" } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 40 Layout.fillWidth: true color: "lightBlue" } } } } 
+1
source

Source: https://habr.com/ru/post/988408/


All Articles