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

时间:2015-12-01 18:42:51

标签: qt qml

潜在相关: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"
        }
    }
}

结果如下:

Attempt at weighted grid layout

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

  

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

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

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

4 个答案:

答案 0 :(得分:15)

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

结果在这里:

QML Grid Layout

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

右上方矩形的描述具有转置的行和列。应该是:

<块引用>

它右侧的一个跨越一和两

行数不正确。应该是:

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

Screenshot showing expected proportions

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

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

答案 3 :(得分:0)

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

enter image description here