【问题标题】:Populate GridLayout with Repeater使用中继器填​​充 GridLayout
【发布时间】:2015-10-06 12:00:42
【问题描述】:

我尝试使用Repeater 将单元格添加到我的GridLayout。我的数据存储在模型中,每个元素包含两个属性:

  • Title
  • Value

我的目标是得到一个GridLayout,在每行的第一个单元格中包含Title,在第二个单元格中包含Value。

GridLayout {
    id: someId
    columns: 2
    rowSpacing: 5
    columnSpacing: 5
    anchors.margins: 5
    anchors.left: parent.left
    anchors.right: parent.right

    Repeater {
        model: myModel
        Label {
            text: modelData.title
        }
        TextArea {
            text: modelData.value
        }
    }
}

但是 QML Repeater 只允许一个元素。有什么想法可以得到我想要的布局吗?

+------------+---------------------------------------+
|            |                                       |
|  title0    |         value0                        |
|            |                                       |
|            |                                       |
+------------+---------------------------------------+
|            |                                       |
|            |                                       |
|  title1    |         value1                        |
|            |                                       |
|            |                                       |
+------------+---------------------------------------+
|            |                                       |
|  title2    |         value2                        |
|            |                                       |
|            |                                       |
+------------+---------------------------------------+

【问题讨论】:

    标签: qt qml repeater qtquick2


    【解决方案1】:

    您可以在GridLayout 中简单地使用两个Repeaters,如下所示:

    import QtQuick 2.5
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    import QtQuick.Controls 1.4
    
    Window {
        width: 600; height: 400; visible: true
    
        GridLayout {
            id: grid
            anchors.fill: parent
            columns: 2
            rowSpacing: 5
            columnSpacing: 5
            anchors.margins: 5
            // example models
            property var titles: [ "title1", "title2", "title3", "title4", "title5" ]
            property var values: [ "value1", "value2", "value3", "value4", "value5" ]
    
            Repeater {
                model: grid.titles
                Label {
                    Layout.row: index
                    Layout.column: 0
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    text: modelData
                }
            }
    
            Repeater {
                model: grid.values
                TextArea {
                    Layout.row: index
                    Layout.column: 1
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    text: modelData
                }
            }
        }
    }
    

    index参数免费提供,存储模型的当前行。

    通过使用Layout.fillWidth附加属性可以控制单列的width。

    当然,属于一列的每个单元格的大小与该列的所有其他单元格的大小相同,这与使用两个 Column 组件发生的情况不同。

    此解决方案有一些缺点,但如果您的目的主要是从模型中打印纯数据,那就很好了。

    【讨论】:

    【解决方案2】:

    您可以使用GridLayout.flow 指定单元格的填充顺序,即按行(GridLayout.LeftToRight)或按列(GridLayout.TopToBottom)。请注意,使用GridLayout.TopToBottom 时应指定number of rows。

    使用此解决方案,skypjack 的(简化)示例将变为:

    import QtQuick 2.5
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    import QtQuick.Controls 1.4
    
    Window {
        width: 600; height: 400; visible: true
    
        GridLayout {
            anchors.fill: parent
    
            // specify the flow and number of rows
            flow: GridLayout.TopToBottom
            rows: repeater.count
    
            Repeater {
                id: repeater
                model: [ "title1", "title2", "title3", "title4", "title5", "title6" ] // example model
                Label {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    text: modelData
                }
            }
    
            Repeater {
                model: [ "value1", "value2", "value3", "value4", "value5", "value6" ]  // example model
                TextArea {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    text: modelData
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      模型视图原则假设每个模型节点由不同的委托组件对象显示。所以我建议你听听@BaCaRoZzo 的评论,并使用Column 而不是GridLayout。当然,QML 非常灵活,您可以这样做:

      Component {
          id: labelDelegate
          Label { text: myList.get(_index / 2).title }
      }
      
      Component {
          id: textAreaDelegate
          TextArea { text: myList.get(_index / 2).value }
      }
      
      ListModel {
          id: myList
          ListElement {title: "title1"; value: "value1"}
          ListElement {title: "title2"; value: "value2"}
          ListElement {title: "title3"; value: "value3"}
      }
      
      GridLayout {
          anchors.fill: parent
          columns: 2
          Repeater {
              model: myList.count * 2
              delegate: Loader {
                  property int _index: index
                  sourceComponent: {
                      if(index % 2)
                          return textAreaDelegate;
                      else
                          return labelDelegate;
                  }
              }
          }
      }
      

      但是在实际项目中使用它太奇怪了。

      【讨论】:

      • 好的,谢谢。我将尝试@BaCaRoZzo 建议的基于列的解决方案。即使我不确定结果是否是我想要的。我认为每行的第一个单元格将具有不同的宽度。让我们看看我是否错了(希望如此^^)
      • 填充列的建议版本工作得很好,但生成的布局不是我想要的。每行的第一个单元格具有不同的宽度。所以这并不是真正的问题解决方案。我会尝试@folibis 的有线解决方案......如果它工作它还不够有线:)
      • Naaah,不要使用它,我已经发布了它作为你不应该做的例子。因此,如果使用Column,您可以为每个Label 设置相同的宽度。或者,更准确地说,您应该查看模型。
      【解决方案4】:

      在Repeater的委托中的Item内嵌套任意数量的元素,并在Item完成时将它们重新设置为GridLayout。

      GridLayout {
          id: grid
          anchors.centerIn: parent
          columns: 2
          rowSpacing: 5
          columnSpacing: 5
          anchors.margins: 5
      
          Repeater {
              model: [
                  { title: "title1 that's long", value: "value1" },
                  { title: "title2 medium",      value: "value2" },
                  { title: "title3",             value: "value3" }
              ]
              delegate: Item {
                  Component.onCompleted: {
                      while (children.length) { children[0].parent = grid; }
                  }
      
                  Label {
                      Layout.alignment: Qt.AlignRight
                      color: "gray"
                      text: modelData.title
                  }
                  TextArea {
                      Layout.fillWidth: true
                      font.bold: true
                      text: modelData.value
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2013-02-17
        • 2014-10-09
        • 2018-05-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 2023-03-25
        • 2020-09-17
        • 2014-04-05
        相关资源
        最近更新 更多