I need a table GUI control that is able to quickly add and show around 100’000 items.
For this reason, “virtual” table control is needed, that loads and shows only visible items.
I tried QTableView and 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();
The problem is that MyModel::data() is called when adding new items out of visible area. And this makes a big slow in performance.
This is my test scenario to be more specific:
- View is created with only 5 elements that can be visible at one time.
- I add 20 items with MyModel::addItems.
- MyModel::data is called for all visible items.
- MyModel::data continues to be called for visible items (1…5) when items 6, 7, 9 … 20 are added.
I was thinking maybe this can be caused by vertical scrollbar that is redrawn when adding new items and seems to make all QListView redraw. But after hiding vertical scrollbar the issue remained.
Please suggest.
I didn’t find out how to prevent endInsertRows call to cause extra invocations of data() method. But calling endInsertRows once for multiple items solves the performance problem. So i call:
instead of calling for 1000 times: