我有一个自定义模型 (QAbstractListModel
) 和一个用作过滤器的自定义代理模型 (QSortFilterProxyModel
)。
在 View 中,当我更新模型时,我需要执行“emit dataChanged(...)
”才能看到显示的更改。
但是随后,代理模型会自动更新(调用filterAcceptsRow
)并且 View 应用相应的过滤选项。
我需要禁用此行为,以便能够更新 View 并仅在单击按钮时应用过滤,而不是自动应用过滤。
例如:
- 我的模型有两个字段:
id (int)
和selected (bool)
- 在 View 中,我仅过滤那些选定的元素(selected == true)
- 应用此过滤器后,我取消选择一个元素。
在当前行为中,该元素会消失,因为模型更改时会应用过滤器。我想显示具有此更改的项目,并仅在单击按钮时应用过滤。
最佳答案
您可以在自定义代理模型中实现一个公共(public)方法,用于启用/禁用过滤器。在我的示例代码中,我使用 Q_INVOKABLE 宏来使 enableFilter()
也可以从 QML 调用。因此,您可以通过调用该方法在单击按钮时启用过滤器。
class ExampleFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit ExampleFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
Q_INVOKABLE void setFilter(const QString & pattern) {
QRegularExpression re(pattern, QRegularExpression::CaseInsensitiveOption);
if (re.isValid()) {
QSortFilterProxyModel::setFilterRegularExpression(pattern);
}
invalidateFilter();
}
Q_INVOKABLE void enableFilter(bool enabled) {
m_enabled = enabled;
invalidateFilter();
}
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override {
if (m_enabled) {
QModelIndex index = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent);
QString str = sourceModel()->data(index, filterRole()).toString();
return str.contains(filterRegularExpression());
}
return true;
}
private:
bool m_enabled = false;
};
实例化模型时,如果未使用 true 显式调用 enableFilter,filterAcceptsRow()
方法将为所有行返回 true。
myFilterProxyModel->setFilterRole(MyListModel::ExampleRole);
myFilterProxyModel->setFilter("^fullstringmatch$");
myFilterProxyModel->setSourceModel(myModel);
//myFilterProxyModel->enableFilter(true);
如果您使用 QML,那么您可以使自定义代理模型对 QML 上下文可见,例如通过将其设置为上下文属性(例如filterProxyModel)并通过调用启用过滤器
filterProxyModel.enableFilter(true)
关于c++ - 更新 sourceModel() 而不在 QSortFilterProxyModel 上应用过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61123100/