如何避免在qml中将列表模型中的列表元素添加到ListView [英] How to avoid a list element in a list model from being added to ListView in qml

查看:91
本文介绍了如何避免在qml中将列表模型中的列表元素添加到ListView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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
}

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

I only want to inflate ListElement which has visible attribute as true. I don't want to inflate the other list elements in the ListView. How can I achieve this?

推荐答案

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

Another solution is to use QSortFilterProxyModel which really filters item, not just hides them. For example:

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 项目中的 Javascript 函数对项目进行排序.

To make the filter flexible it uses Javascript function from FilterModel item to sort items.

所以用法是:

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 以跳过项目.

All the magic takes place in FilterModel.filter(). It should just return false to skip an item.

这篇关于如何避免在qml中将列表模型中的列表元素添加到ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆