Best way to fill a QTableView
-
Hi all,
I have a question, lets suppose we need to show 50.000 rows and 20 columns in a qtableview, what is the faster way to load all this data into a qtableview, or maybe is there another solution?
I load 2500 rows and 15 cols from a table and it took over 8 segs, so I want to now if I'm doing something wrong.
-
The QTableView is just a view. It doesn't contain any data. The model does. Thus you load data into the model.
So what model are you using? And how are you loading the data into whatever model you are using?
If you insert the items one-by-one into the model and after each item inserted the view is updated (redrawn), then this clearly will be slow. So, for example, when you implement the model, you should call beginResetModel() before you start inserting new items and not call endResetModel() unless all items have been inserted - rather than calling reset() after each item inserted. This all depends on your model implementation though...
-
Hi MuldeR, thanks for your replay.
I use QStandardItemModel and it is filled this way:
@
void DTableView::setModelData(QList<QStringList> modelData, bool readOnly)
{
QApplication::setOverrideCursor(Qt::WaitCursor);
this->readOnly = readOnly;
setHeaders();
emit loadStarted(tr("Loading records..."), 2000, 0);
itemModel = new QStandardItemModel(modelData->count(), headersList->count());
itemModel->blockSignals(true);
connect(itemModel, SIGNAL(itemChanged(QStandardItem)), this, SLOT(itemChangedSlot(QStandardItem*)));
for (int row = 0; row < modelData->count(); row++) {
for (int column = 0; column < headersList->count(); column++) {
itemModel->setHorizontalHeaderItem(column, new QStandardItem(QIcon(headersList->at(column).at(2)), headersList->at(column).at(0)));
QStandardItem *item;
if (column == 0)
item = new QStandardItem(QIcon(modelData->at(row).at(0)), modelData->at(row).at(column + 1));
else
item = new QStandardItem(modelData->at(row).at(column + 1));
if (headersList->at(column).at(3) == "Right")
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
if (headersList->at(column).at(3) == "ToBytes") {
item->setText(StaticFunctions::bytesConvertor(item->text()));
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
itemModel->setItem(row, column, item);
if (!this->readOnly)
itemModel->setData(itemModel->index(row, column, QModelIndex()), modelData->at(row).at(column + 1), Qt::UserRole);
}
//emit loadProgress(tr("Loading records..."), 2000, row * 100 / modelData->count());
}
QItemSelectionModel *oldModel = selectionModel();
setModel(itemModel);
delete oldModel;
resizeColumnsToContents();
resizeRowsToContents();
setSortingEnabled(true);
sortByColumn(0, Qt::AscendingOrder);
itemModel->blockSignals(false);
emit loadStarted(tr("Records loaded."), 2000, 100);
QApplication::restoreOverrideCursor();
}
@ -
So, from what I can see, you are filling QStandardItemModel while it's still "offline", i.e. you are assigning the model to the view only after it has been completely filled. That's good, because this way the view won't refresh while you are still modifying the model. Anyway, if pumping all your data into a QStandardItemModel takes too long, I think all you could do is implementing your own model class, derived from QAbstractTableModel . Instead of inserting all items into the model item-by-item, your own model class would simply wrap the QList<QStringList>. Of course it means you would then have to implement your own data(), rowCount() and columnCount() methods.
--
See also:
http://qt-project.org/doc/qt-4.8/qabstracttablemodel.html#details -
I'll take a look in QAbstractTable.
Thanks.