QAbstractTableModel :: data方法调用次数过多

时间:2011-12-13 01:18:24

标签: c++ qt qtableview

我需要一个表GUI控件,能够快速添加和显示大约100'000个项目。 出于这个原因,需要“虚拟”表控件,它只加载和显示可见项。 我尝试了QTableView和QAbstractTableModel:

class MyModel : public QAbstractTableModel
{
public:
MyModel(QObject * parent, IDataSource* dataSource) 
    : QAbstractTableModel(parent), m_dataSource(dataSource) {}

int rowCount(const QModelIndex& parent = QModelIndex()) const
{
    return m_dataSource->rowCount();
}

int columnCount(const QModelIndex& parent = QModelIndex()) const
{
    return 3;
}

QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
    if (role == Qt::DisplayRole)
    {
            return m_dataSource->cell(index.row(), index.column());
    }
    return QVariant();
}

bool addItem()
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    endInsertRows();
    return true;
}

private:
IDataSource* m_dataSource;
};

...

MyModel* model = new MyModel(this, this);
m_ui.tableView->setModel(model);
m_ui.tableView->show();

问题是在可见区域外添加新项目时会调用MyModel :: data()。这使得性能大幅下降。 这是我更具体的测试场景:

  1. 创建的视图只包含一次可见的5个元素。
  2. 我使用MyModel :: addItems添加了20个项目。
  3. 为所有可见项调用MyModel :: data。
  4. 当添加第6,7,9 ... 20项时,继续为可见项目(1 ... 5)调用MyModel :: data。
  5. 我想也许这可能是由添加新项目时重绘的垂直滚动条引起的,并且似乎使所有QListView重绘。但在隐藏垂直滚动条之后,问题仍然存在。 请建议。

2 个答案:

答案 0 :(得分:2)

我没有找到如何防止endInsertRows调用导致额外调用data()方法。但是为多个项调用endInsertRows一次可以解决性能问题。所以我打电话给:

beginInsertRows(QModelIndex(), rowCount(), rowCount() + 1000);
endInsertRows();

而不是要求1000次:

beginInsertRows(QModelIndex(), rowCount(), rowCount());
endInsertRows();

答案 1 :(得分:0)

dataSource-> cell()实现的渐近复杂性是什么? data()确实可能被调用很多次,如果你把例如更多顶部的QSortFilterProxyModel用于排序。为了确保具有大量数据的项目视图的性能,data()必须只需要恒定的时间来实现。