【问题标题】:How can I create a QML GridLayout with items of proportionate sizes?如何创建具有比例大小的项目的 QML GridLayout?
【发布时间】:2015-12-01 18:42:50
【问题描述】:

潜在相关:https://stackoverflow.com/a/30860285/3363018

我一直在尝试创建一个 QML 布局,其中的项目跨越可变数量的行和列。因此,例如,一个跨越两行四列的矩形,其右侧的一个跨越一行两列,而下方的一个跨越三行五列。创建它的一般尝试如下:

import QtQuick 2.5
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    GridLayout {
        anchors.fill: parent

        columns: 5
        rows: 2

        Rectangle {
            Layout.column: 0
            Layout.columnSpan: 4
            Layout.row: 0
            Layout.rowSpan: 2

            Layout.fillHeight: true
            Layout.fillWidth: true

            color: "red"
        }

        Rectangle {
            Layout.column: 4
            Layout.columnSpan: 1
            Layout.row: 0
            Layout.rowSpan: 2

            Layout.fillHeight: true
            Layout.fillWidth: true

            color: "green"
        }

        Rectangle {
            Layout.column: 0
            Layout.columnSpan: 5
            Layout.row: 2
            Layout.rowSpan: 3

            Layout.fillHeight: true
            Layout.fillWidth: true

            color: "blue"
        }
    }
}

结果如下:

如您所见,Layout.rowSpan 和 Layout.columnspan 似乎不起作用。相反,前两行似乎占用 1:1 而不是 4:1,顶部与底部的比例是 1:1 而不是 2:3。我怀疑这与 Layout.fillHeight 和 Layout.fillWidth 有关。 The documentation 状态:

如果此属性为真,则项目将尽可能宽,同时 尊重给定的约束。

但我不确定在这种情况下“给定的约束”是什么。我曾希望它包括行和列跨度,但似乎没有。

我可能可以直接计算项目的宽度和高度(或者可能是 Layout.preferredWidth 和 Layout.preferredHeight),但这似乎会使 Layout.rowSpan 和 Layout.columnSpan 完全多余。有没有办法根据网格行和列自动计算高度?

【问题讨论】:

  • 声明中有错误:行数应该是5,而不是2。这并不能解决问题。

标签: qt qml


【解决方案1】:

右上矩形的描述已转置了行和列。应该是:

它右侧的一个,跨越一个 和两个

行数不正确。应该是:

columns: 5
rows: 5

将首选宽度和高度指定为百分比或单位。我使用下面的单位是因为它更容易与您的 4:1 和 2:3 比例相关:

GridLayout {
    anchors.fill: parent

    columns: 5
    rows: 5                        // was 2

    Rectangle {
        Layout.column: 0
        Layout.columnSpan: 4
        Layout.row: 0
        Layout.rowSpan: 2
        Layout.preferredWidth: 4   // 4 of 5 cols
        Layout.preferredHeight: 2  // 2 of 5 rows
        Layout.fillHeight: true
        Layout.fillWidth: true

        color: "red"
    }

    Rectangle {
        Layout.column: 4
        Layout.columnSpan: 1
        Layout.row: 0
        Layout.rowSpan: 2
        Layout.preferredWidth: 1   // 1 of 5 cols
        Layout.preferredHeight: 2  // 2 of 5 rows
        Layout.fillHeight: true
        Layout.fillWidth: true

        color: "green"
    }

    Rectangle {
        Layout.column: 0
        Layout.columnSpan: 5
        Layout.row: 2
        Layout.rowSpan: 3
        Layout.preferredHeight: 3  // 3 of 5 rows
        Layout.fillHeight: true
        Layout.fillWidth: true

        color: "blue"
    }
}

以下是使用百分比来实现相同结果的最少代码:

GridLayout {
    anchors.fill: parent
    columns: 2

    Rectangle {
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.preferredWidth: 80
        Layout.preferredHeight: 40
        color: "red"
    }

    Rectangle {
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.preferredWidth: 20
        Layout.preferredHeight: 40

        color: "green"
    }

    Rectangle {
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.columnSpan: 2
        Layout.preferredWidth: 100
        Layout.preferredHeight: 60

        color: "blue"
    }
}

【讨论】:

    【解决方案2】:

    我遇到了和你一样的问题,但我认为很容易误解 GridLayout 的作用。如果你有 5 列和 2 行的网格,你会得到这样的结果,其中每个 O 代表一个单元格:

    grid
    OOOOO
    OOOOO
    

    rowSpan 决定了对象的TALL

    columnSpan 确定对象的WIDE 程度。

    您希望将它们放入此网格中:

    r1      r2     r3
    OOOO    OO   OOOOO
    OOOO         OOOOO
                 OOOOO
    

    不难看出,但它们不适合。

    这是我对 12x12 网格的解决方案,应该很容易理解。 GridLayout 似乎不会自动知道分配给其子项的宽度和高度。但没关系,你可以很容易地定义它。本质上,我将矩形传递给我的两个短的两个函数。您可以传递 rowSpan 或 columnSpan 但我更喜欢这种方式,因为我不必记住哪个函数需要什么:

    GridLayout {
        id : grid
        anchors.fill: parent
        rows    : 12
        columns : 12
        property double colMulti : grid.width / grid.columns
        property double rowMulti : grid.height / grid.rows
        function prefWidth(item){
            return colMulti * item.Layout.columnSpan
        }
        function prefHeight(item){
            return rowMulti * item.Layout.rowSpan
        }
    
        Rectangle {
            color : 'red'
            Layout.rowSpan   : 10
            Layout.columnSpan: 2
            Layout.preferredWidth  : grid.prefWidth(this)
            Layout.preferredHeight : grid.prefHeight(this)
        }
        Rectangle {
            color : 'yellow'
            Layout.rowSpan   : 10
            Layout.columnSpan: 10
            Layout.preferredWidth  : grid.prefWidth(this)
            Layout.preferredHeight : grid.prefHeight(this)
        }
        Rectangle {
            id : greenRect
            color : 'green'
            Layout.rowSpan : 2
            Layout.columnSpan : 12
            Layout.preferredWidth  : grid.prefWidth(this)
            Layout.preferredHeight : grid.prefHeight(this)
        }
    }
    

    这里的结果:

    【讨论】:

      【解决方案3】:

      如果您不打算在网格中留下任何空白空间,您可以通过将首选尺寸绑定到跨度来使宽度和高度与跨度成比例。

      Layout.fillWidth: true
      Layout.fillHeight: true
      Layout.preferredWidth: Layout.columnSpan
      Layout.preferredHeight: Layout.rowSpan
      

      【讨论】:

        【解决方案4】:

        @Kao 建议绑定到 columnSpan 和 rowSpan。这是有效的,因为它们是单位比例。

        如果一行上的所有元素都将Layout.fillWidth 设置为true,则使用它们的首选宽度来确定它们的比例宽度。将一个元素的preferredWidth 绑定到它的columnspan 建立了一个比率,GridLayout 使用它来计算元素的宽度:5 列网格中的跨度为 4 会导致元素占据网格总宽度的 80%。列中的元素也是如此。

        此解决方案使用 Qt 5.15 内联组件:

        GridLayout {
            anchors.fill: parent
            columns: 5
            rows: 5
        
            component ProportionalRect: Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredWidth: Layout.columnSpan
                Layout.preferredHeight: Layout.rowSpan
            }
        
            ProportionalRect {
                Layout.columnSpan: 4
                Layout.rowSpan: 2
        
                color: "red"
            }
        
            ProportionalRect {
                Layout.columnSpan: 1
                Layout.rowSpan: 2
        
                color: "green"
            }
        
            ProportionalRect {
                Layout.columnSpan: 5
                Layout.rowSpan: 3
        
                color: "blue"
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2020-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-06
          • 1970-01-01
          • 2017-09-16
          • 1970-01-01
          • 2022-09-23
          相关资源
          最近更新 更多