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