处理近似大数据集时加快QSortFilterProxyModel过滤

时间:2016-10-13 17:20:05

标签: c++ qt qt5 qabstractitemmodel qsortfilterproxymodel

之前,我向a question询问了多列过滤,我们需要表示符合多种过滤模式的行。

现在处理大表时(通过big我意味着大约200,000行和4列)如果我们有一个大表(通常这对于过滤模式的前2个字符最差),过滤会变慢。

那你对此有什么建议?

注意:我有自己的高性能源数据模型(而不是QStandardItemModel),基于this示例,在大约1秒钟内为该行数提供视图

编辑1

改变我的方法:

bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
if (/* filtering is enable*/) {
    bool _res = sourceModel()->data(sourceModel()->index(source_row, 0, source_parent)).toString().contains( /*RegExp for column 0*/);
    for (int col = 0; col < columnCount(); col++) {
        _res &= sourceModel()->data(sourceModel()->index(source_row, col + 1, source_parent)).toString().contains(/*RegExp for column col + 1*/);
    }
    return _res;
}
return true;

}

对此:

bool DataFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
    if (_enable) {
        return (sourceModel()->index(source_row, 0, source_parent.child(source_row, 0)).data().toString().contains( /*string for column 0*/ ))
            && sourceModel()->index(source_row, 1, source_parent.child(source_row, 1)).data().toString().contains(/*string for column 1*/))
            && sourceModel()->index(source_row, 2, source_parent.child(source_row, 2)).data().toString().contains(/*string for column 2*/))
            && sourceModel()->index(source_row, 3, source_parent.child(source_row, 3)).data().toString().contains(/*string for column 3*/));
    }
    return true;
}

看起来很完美。现在过滤就像魅力一样毫不拖延

1 个答案:

答案 0 :(得分:1)

如果项目数量非常高,您无法一次性加载它们,您可以尝试仅在视图中需要时批量添加项目。这可以通过覆盖canFetchMore()fetchMore()来完成。看看Fetch More Example。请注意,这是%内部从数据库加载大型模型的方式,请参阅here

以下是使用此方法实现模型的方法:

QSqlQueryModel

如果您确定您的真正瓶颈是过滤,您可能还想避免使用@DmitrySazonov,子类#include <QApplication> #include <QtWidgets> class MyTableModel : public QAbstractTableModel{ public: explicit MyTableModel(int rowCount, QObject* parent=nullptr) :QAbstractTableModel(parent),currentRowCount(0),wholeRowCount(rowCount){} ~MyTableModel(){} int rowCount(const QModelIndex &parent) const override{ if(parent.isValid()) return 0; return currentRowCount; } int columnCount(const QModelIndex &parent) const override{ if(parent.isValid()) return 0; return 2; } QVariant data(const QModelIndex &index, int role) const override{ Q_ASSERT(index.row()<currentRowCount); QVariant val; if(role== Qt::DisplayRole || role== Qt::EditRole){ switch(index.column()){ case 0: val= QString("#%1").arg(index.row()+1, 8, 10, QChar('0')); break; case 1: val= rows[index.row()]; break; } } return val; } bool canFetchMore(const QModelIndex &parent) const override{ if(parent.isValid()) return false; return (currentRowCount < wholeRowCount); } void fetchMore(const QModelIndex& /* index */) override{ int toFetch= qMin(52, wholeRowCount-currentRowCount); char ch = 'A'; beginInsertRows(QModelIndex(), currentRowCount, currentRowCount+toFetch-1); for(int i=0; i<toFetch; i++){ rows+= QString(QChar(ch)); if(ch == 'Z') ch = 'A'; else ch++; } currentRowCount+= toFetch; endInsertRows(); } private: int currentRowCount; int wholeRowCount; QStringList rows; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; QVBoxLayout layout(&w); QLineEdit filterLineEdit; QTableView tableView; layout.addWidget(&filterLineEdit); layout.addWidget(&tableView); MyTableModel model(200000); QSortFilterProxyModel proxyModel; proxyModel.setSourceModel(&model); proxyModel.setFilterKeyColumn(-1); tableView.setModel(&proxyModel); QObject::connect(&filterLineEdit, &QLineEdit::textChanged, [&](){ proxyModel.setFilterFixedString(filterLineEdit.text()); }); w.show(); return a.exec(); } 所指示的正则表达式,覆盖filterAcceptsRow()并在那里提供您的算法而不是使用一般基于QSortFilterProxyModel的过滤器。

要考虑的另一件事是避免在过滤器变窄时检查已经过滤的行,看看this question