如何使用大小成比例的项目创建 QML GridLayout?

问题描述 投票:0回答:4

可能相关: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
有关。 文档指出:

如果此属性为 true,则该项目将尽可能宽,同时 尊重给定的限制。

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

我可能可以直接计算项目的宽度和高度(或者可能是

Layout.preferredWidth
Layout.preferredHeight
),但这似乎使得
Layout.rowSpan
Layout.columnSpan
完全多余。有没有办法根据网格行和列自动计算高度?

qt qml
4个回答
20
投票

我遇到了和你一样的问题,但我认为很容易误解 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)
    }
}

结果在这里:


2
投票

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

右侧的一个跨越一列和两行

行数不正确。应该是:

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
投票

如果一行上的所有元素都设置了

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" } }


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.