如何避免列表模型中的列表元素被添加到qml中的ListView中

时间:2016-11-25 09:16:59

标签: qt listview delegates qml qtquick2

我有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充气。我不想夸大ListView中的其他列表元素。 我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

你自己几乎解决了你的问题。您只需在视图的visible: model.visible内添加delegate(此处:sourceDelegate的实施内部)。例如,您将拥有以下内容:

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

答案 1 :(得分:2)

另一种解决方案是使用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项目中的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来跳过一个项目。