【问题标题】:Is it possible to show only certain indexes of a QML listview?是否可以仅显示 QML 列表视图的某些索引?
【发布时间】:2015-03-09 11:35:32
【问题描述】:

是否可以在 QML 列表视图中仅显示某些索引或一系列索引?

我有一个列表模型,其中包含我正在重用的大量信息。是否可以有一个列表,例如,仅显示索引 5 到 8?

【问题讨论】:

    标签: qt listview qml


    【解决方案1】:

    提出一个纯 QML 方法来解决这个问题会很有趣。当然,这不是捷径,但它是一个解决方案。

    该方法基于models QML 模块中的DelegateModel。它在文档中写道:

    DelegateModel 类型封装了一个模型和委托 为模型中的项目实例化。

    通常不需要创建 DelegateModel。然而,它可以 对操作和访问 modelIndex 很有用 QAbstractItemModel 子类用作模型。另外,DelegateModel 与Package一起使用来为多个视图提供代理, 并使用DelegateModelGroup 对委托项目进行排序和过滤

    DelegateModel 确实是一种强大的类型,具有很多功能(有关详细信息,请参阅链接文档)。 DelegateModel 的两个关键属性是 groupsfilterOnGroup。前者基本上是DelegateModelGroup 的列表,它定义了要过滤或不过滤的项目。后者用于应用特定过滤器,即选择包含在groups 中的特定DelegateModelGroup,只需将属性设置为所选组的名称即可。

    请注意,提及VisualDataModelDelegateModel 是相同的,因为第一个是出于兼容性原因提供的(同样适用于VisualDataGroup w.r.t. DelegateModelGroup)。

    总结一下,可以通过这种方式过滤完整 QML 中的模型:

    1. 创建一个model 作为过滤模型的来源
    2. model 提供给VisualDataModel/DelegateModel
    3. 定义VisualDataGroup/DelegateModelGroup(或多个)-将includeByDefault设置为false以避免自动添加原始模型中的所有
    4. 定义填充组的策略
    5. filterOnGroup 设置为所选组
    6. 将视图模型设置为VisualDataModel 模型

    在下一个示例中,为简单起见,我只在Component.onCompleted 事件处理程序期间填充组一次。如前所述,应该选择策略,这取决于具体的用例。

    在示例中,只有key 角色等于0 的项目被添加到key0 组中,即ListView 中显示的组。上述清单在代码中突出显示。

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import QtQuick.Window 2.0
    
    ApplicationWindow {
        title: qsTr("DelegateModel test")
        width: 200
        height: 350
        visible: true
    
        ListView {
            id: displayListView
            anchors.fill: parent
            spacing: 5
            //
            model: displayDelegateModel             // 6
        }
    
        ListModel {                                 // 1
            id: myModel
            ListElement { vis: "One"; key: 0; }
            ListElement { vis: "two"; key: 1; }
            ListElement { vis: "Three"; key: 0; }
            ListElement { vis: "Four"; key: 0; }
            ListElement { vis: "Five"; key: 1; }
            ListElement { vis: "Six"; key: 1; }
            ListElement { vis: "Seven"; key: 0; }
        }
    
        VisualDataModel {
            id: displayDelegateModel
    
            delegate:  Rectangle {
                anchors.left: parent.left
                anchors.right: parent.right
                height: 25
                color: "steelblue"
    
                Text {
                    text: vis
                    anchors.centerIn: parent
                    font.bold: true
                    font.pixelSize: 20
                }
            }
    
            model: myModel                          // 2
    
            groups: [
                VisualDataGroup {                   // 3
                    includeByDefault: false         // NECESSARY TO AVOID AUTOADDITION
                    name: "key0"
                }
            ]
    
            filterOnGroup: "key0"                   // 5
    
            Component.onCompleted: {                // 4
                var rowCount = myModel.count;
                items.remove(0,rowCount);
                for( var i = 0;i < rowCount;i++ ) {
                    var entry = myModel.get(i);
                    if(entry.key == 0) {
                        items.insert(entry, "key0");
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢你的例子,不过我有一个问题。 items.insert(entry, "key0") 将 "key0" 属性插入到项目中,以便以后可以再次对其进行排序?
    • 嘿,嗯,我刚刚意识到...这个 delegateModel 是新的吗?因为在 QML 中不支持树模型,并且在我正在阅读的文档中它支持树模型操作
    • 忘记添加“@name”:D,嗯,它不起作用,没关系这个评论
    • 取决于命名,但很久以前就支持了。 “key0”就像一个过滤器:该组内的所有内容都可以从完整列表中排序出来。
    • 有没有办法按角色做一个简单的过滤?
    【解决方案2】:

    是的,这是可能的。您需要覆盖QSortFilterProxyModel::filterAcceptRow 方法。

    MyFilterModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
    {
      if ( source_row > 5 && source_row < 8 )
        return true;
    
      return false;
    }
    //...
    MyFilterModel *filter = new MyFilterModel();
    filter->setSourceMoldel( yourSourceModel );
    view->setModel( filter );
    

    【讨论】:

      【解决方案3】:

      您可以通过在某些条件下将委托可见性设置为 false 来实现:

        Grid {
          anchors.fill: parent
          rows: 4
          columns: 5
          spacing: 5
          Repeater {
            model: 20
            delegate: Rectangle {
              width: 50
              height: 50
              visible: index >= 5 && index <= 8 // show only certain indices
              Text {
                anchors.centerIn: parent
                text: index
              }
            }
          }
        }
      

      在内存中创建隐藏项会产生一些开销,因此如果您处理非常大的模型并仅显示其中的一小部分,则不是最佳选择。

      【讨论】:

      • 以及如何检测滚动请求以更改索引?
      • @DrlSherifOmran 如果您绑定到引用具有更改通知的属性的表达式,如果它们的值发生更改,则会导致自动重新评估可见性。虽然对于滚动,您已经准备好使用组件。
      • 这很奏效!我用它来创建分页。 visible: currentPage == 1 ? index &lt; 6 : index &gt;= 6 之类的东西,其中 currentPage 是根属性。没有警告。刚刚工作。
      • @HeathRaftery - 有更好的选择,你可以使用过滤,这样你就不会因为大量不可见的对象占用内存而告终。
      • 分数?更好的?占用内存?这些似乎都不适用于我的申请,所以在这种情况下可能不是?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 2018-05-13
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多