具有可变列数的QML Repeater和QML Grid Layout

时间:2017-12-04 17:10:44

标签: qt qml qtquick2 qtquickcontrols2

我有一个由具有某些属性的对象组成的模型,例如:

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        color: "green"
        cost: 2.45
    }
    ListElement {
        name: "Orange"
        color: "orange"
        cost: 3.25
    }
    ListElement {
        name: "Banana"
        color: "yellow"
        cost: 1.95
    }
}

现在我想使用GridLayout显示此模型。对于每个属性,我想在GridLayout中使用一个元素,例如:

GridLayout {
    columns: 3

    Text { text: "Apple" }
    Rectangle { color: "green" }
    SpinBox { value: 2.45 }

    Text { text: "Orange" }
    Rectangle { color: "orange" }
    SpinBox { value: 3.25 }

    Text { text: "Banana" }
    Rectangle { color: "yellow" }
    SpinBox { value: 1.95 }
}

关键是我可以轻松更改columns的{​​{1}}属性并使我的布局更窄(例如适合小屏幕)。我可以使用Repeater来填充GridLayout。但是,这种方法会以错误的顺序填充GridLayout

GridLayout

使用GridLayout { columns: 3 Repeater { model: fruitModel Text { text: name } } Repeater { model: fruitModel Rectangle { color: color } } Repeater { model: fruitModel SpinBox { value: value } } } Layout.column附加属性是浪费,因为我想轻松更改Layout.row中的列数。

有没有办法逐行填充GridLayout来自模型的数据?

UPD1:

我想要的行为:

enter image description here

GridLayout

UPD2: 来自@ m7913d的修改变体:

GridLayout {
    columns: parent.width > 235 ? 3 : 1

    Text { text: "Apple" }
    Rectangle { color: "green"; width: 40; height: 40 }
    SpinBox { value: 2 }

    Text { text: "Orange" }
    Rectangle { color: "orange"; width: 40; height: 40 }
    SpinBox { value: 3 }

    Text { text: "Banana" }
    Rectangle { color: "yellow"; width: 40; height: 40 }
    SpinBox { value: 1 }
}

这是有效但不易修改的解决方案,有时在布局调整大小时会有消息GridLayout { id: layout property int maxColumns: 3 columns: parent.width > 235 ? maxColumns : 1 Repeater { model: fruitModel Text { text: name Layout.row: layout.columns == maxColumns ? index : (maxColumns * index) Layout.column: 0 } } Repeater { model: fruitModel Rectangle { Layout.preferredWidth: 30 Layout.preferredHeight: 30 color: col Layout.row: layout.columns == maxColumns ? index : (maxColumns * index + 1) Layout.column: layout.columns == maxColumns ? 1 : 0 } } Repeater { model: fruitModel SpinBox { value: val Layout.row: layout.columns == maxColumns ? index : (maxColumns * index + 2) Layout.column: layout.columns == maxColumns ? 2 : 0 } } }

3 个答案:

答案 0 :(得分:1)

一种可能的方法是使用条件列/行索引扩展this method

GridLayout {
    id:gridLayout
    columns: parent.width > 235 ? 3 : 1

    Repeater {
        model: fruitModel
        implicitHeight: 50
        Text {
            text: name
            Layout.row: gridLayout.columns == 3 ? index : 3 * index
            Layout.column: 0
        }
    }

    Repeater {
        model: fruitModel
        Rectangle {
            color: model.color
            implicitWidth: 50
            implicitHeight: 50
            Layout.row: gridLayout.columns == 3 ? index : 3 * index + 1
            Layout.column: gridLayout.columns == 3 ? 1 : 0
        }
    }

    Repeater {
        model: fruitModel
        SpinBox {
            value: value
            Layout.row: gridLayout.columns == 3 ? index : 3 * index + 2
            Layout.column: gridLayout.columns == 3 ? 2 : 0
        }
    }
}

答案 1 :(得分:1)

我会使用ColumnRow(或任何其他安排)填充的Column作为代表。

Column {
    id: rootCol
    anchors.fill: parent
    Repeater {
        model: fruitModel
        delegate: rootCol.width > 300 ? rowDel : colDel
    }

    Component {
        id: rowDel
        Row {
            Text { width: 100; height: 50; text: model.name }
            Rectangle { width: 50; height: 50; color: model.color }
            SpinBox { width: 150; height: 50; value: model.cost }
        }
    }

    Component {
        id: colDel
        Column {
            Text { width: 100; height: 50; text: model.name }
            Rectangle { width: 50; height: 50; color: model.color }
            SpinBox { width: 150; height: 50; value: model.cost}
        }
    }
}

或者也许:

Column {
    id: rootCol
    anchors.fill: parent
    Repeater {
        model: fruitModel
        delegate: Flow {
            anchors {
                left: parent.left
                right: parent.right
            }

            Text { width: 100; height: 50; text: model.name }
            Rectangle { width: 50; height: 50; color: model.color }
            SpinBox { width: 150; height: 50; value: model.value }
        }
    }
}

答案 2 :(得分:1)

这是另一种解决方案:

  

理念:以正确的顺序添加孩子

为此,我们需要确保模型条目的所有Item

GridLayout {
    id: gl
    columns: parent.width > 235 ? 3 : 1
}
Instantiator {
    model: fruitModel
    delegate: QtObject {
        property Item text: Text { parent: gl; text: model.name }
        property Item rect: Rectangle { parent: gl; color: model.color; width: 50; height: 50; }
        property Item spin: SpinBox { parent: gl; value: model.cost; }
    }
}
  

注意:当插入或重新排序模型中的条目时,这将失败,因为在此解决方案中始终附加条目。
  除此之外,它将自动支持列更改