【问题标题】:How to avoid a list element in a list model from being added to ListView in qml如何避免列表模型中的列表元素被添加到qml中的ListView
【发布时间】:2016-11-25 09:16:59
【问题描述】:

我有一个ListModel

ListModel {
    id: sourceModel
    ListElement { sourceType: "Christian's Galexy"; sourceName: "Bluetooth"; visible: true }
    ListElement { sourceType: "BBC Radio"; sourceName: "DAB"; visible: true }
    ListElement { sourceType: "Media Library"; sourceName: "";  visible: false }
    ListElement { sourceType: "Chris's Music"; sourceName: "USB"; visible: false }
}

我有一个ListView

ListView {
    id: source_list
    width: parent.width; height: parent.height
    spacing: 6
    model: sourceModel
    delegate: sourceDelegate
    focus: true
    interactive: true
    clip: true
    boundsBehavior: Flickable.StopAtBounds
}

我只想膨胀 ListElement,它的可见属性为 true。我不想夸大ListView 中的其他列表元素。 我怎样才能做到这一点?

【问题讨论】:

    标签: qt listview delegates qml qtquick2


    【解决方案1】:

    另一种解决方案是使用QSortFilterProxyModel 真正过滤项目,而不仅仅是隐藏它们。例如:

    FilterModel.h

    class FilterModel : public  QSortFilterProxyModel
    {
        Q_OBJECT
        Q_PROPERTY(QByteArray filterRole READ filterRole WRITE setFilterRole NOTIFY filterRoleChanged)
    public:
        FilterModel(QObject *parent = Q_NULLPTR);
    
        QByteArray filterRole() const;
        void setFilterRole(const QByteArray roleName);
    
    protected:
        bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const Q_DECL_OVERRIDE;
    
    private:
        QByteArray m_filterRole;
    signals:
        void filterRoleChanged();
    };
    

    FilterModel.cpp

    FilterModel::FilterModel(QObject *parent) :
        QSortFilterProxyModel(parent)
    {}
    
    QByteArray FilterModel::filterRole() const
    {
        return m_filterRole;
    }
    
    void FilterModel::setFilterRole(const QByteArray roleName)
    {
        if(roleName != m_filterRole) {
            m_filterRole = roleName;
            emit filterRoleChanged();
        }
    }
    
    bool FilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
    {
        QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
        int role = sourceModel()->roleNames().key(m_filterRole,(int)Qt::DisplayRole);
        QVariant data = index.data(role);
        QVariant returnedValue;
        QMetaObject::invokeMethod(const_cast<FilterModel *>(this), "filter",
                Q_RETURN_ARG(QVariant, returnedValue),
                Q_ARG(QVariant, data));
    
        return returnedValue.toBool();
    }
    

    为了使过滤器灵活,它使用来自FilterModel item 的 Javascript 函数对项目进行排序。

    所以用法是:

    ListModel {
        id: listModel
        ListElement { name: "name1"; visible: true }
        ListElement { name: "name2"; visible: true }
        ListElement { name: "name3"; visible: false }
        ListElement { name: "name4"; visible: true }
    }
    
    FilterModel {
        id: proxyModel
        sourceModel: listModel
        filterRole: "visible"
        function filter(value)
        {
            return value;
        }
    }
    
    ListView {
        model: proxyModel
        anchors.fill: parent
        spacing: 2
        delegate: Rectangle {
            height: 30;
            width: parent.width
            border{ width: 1; color: "#999" }
            color: "#DEDEDE"
            Text {
                anchors { centerIn: parent; margins: 5 }
                text: name
                verticalAlignment: Text.AlignVCenter
            }
        }
    }
    

    所有的魔法都发生在FilterModel.filter()。它应该只返回 false 以跳过一个项目。

    【讨论】:

    • 你不需要写model Q_PROPERTYQAbstractProxyModel 中已经有一个sourceModel 属性。您应该循环模型的所有角色并检索每个角色的数据并将其传递给 js 函数,而不仅仅是获取默认角色。或者,您可以在这里使用我仍然处于实验阶段的库:github.com/oKcerG/SortFilterProxyModel/tree/feature/…
    • 感谢@GrecKo 的笔记和有用的链接,我已经更新了我的示例。
    • 很好的解决方案!也许还需要补充一点,您必须通过 qmlRegisterType&lt;FilterModel&gt;("cpp.filtermodel", 1, 0, "FilterModel"); 注册这个新的 QML-Type 并将其包含在带有 import cpp.filtermodel 1.0 的 qml 文件中。
    【解决方案2】:

    您几乎自己解决了您的问题。您只需在视图的delegate 中添加visible: model.visible(此处:在sourceDelegate 的实现中)。例如,你会有这样的东西:

    delegate: Rectangle {
        width: parent.width; height: 30
        visible: model.visible
        border.width: 2
        Text {
            anchors.centerIn: parent
            text: "\"" + sourceType + "\", " + sourceName
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-04
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      相关资源
      最近更新 更多