Proper way of resizing model in QTableView
-
I have a
QTableView
that I'm populating with a subclass ofQAbstractTableModel
. The model is updated via a slot that receives the information and emitsdataChanged
. However, that doesn't seem to be enough for the view to show the new rows. I've tried also emittinglayoutChanged
afterdataChanged
in my slot and it works, but I'm not sure if that's correct. I've read the docs and dunno whether I should usebeginInsertRows
instead.I want to know if I'm doing it correctly or there's a different way.
Anyway, here's a minimal compilable example for you to try, you can just copy and paste it in a
.cpp
and compile it.#include <QApplication> #include <QAbstractTableModel> #include <QDateTime> #include <QVBoxLayout> #include <QTimer> #include <QDebug> class MyModel : public QAbstractTableModel { public: int rowCount(const QModelIndex &parent) const { return mRecords.count(); } int columnCount(const QModelIndex &parent) const { return 2; } QVariant data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole) return QVariant(); Record r = mRecords.at(index.row()); return index.column() == 0 ? r.date : r.value; } QVariant headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal) return QVariant(); if (role != Qt::DisplayRole) return QVariant(); if (section == 0) return QString("Date"); else if (section == 1) return QString("Number"); return QVariant(); } public slots: void addValue() { Record r = { QDateTime::currentDateTime().toString(), QString::number(qrand() % 1000) }; mRecords << r; qDebug() << "Added record" << r.date << r.value; emit dataChanged(index(mRecords.count() - 1, 0), index(mRecords.count() - 1, 1)); emit layoutChanged(); } private: struct Record { QString date; QString value; }; QList<Record> mRecords; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; QTableView * table = new QTableView(&w); MyModel model; table->setModel(&model); QVBoxLayout * layout = new QVBoxLayout(&w); layout->addWidget(table); QTimer t; QObject::connect(&t, &QTimer::timeout, [&] { model.addValue(); }); t.start(250); w.show(); return a.exec(); }
-
@JoseTomasTocino
I don't know about your code. ButdataChanged
signal must only be emitted for existing rows whose content is changed. You must emitbegin/endInsert/DeleteRows
instead for row inserts/deletes to make it work correctly. -
I already stated in my post that I think I should use beginInsertRows / endInsertRows, I was asking for the proper way of doing it.
-
http://doc.qt.io/qt-5/qabstractitemmodel.html#subclassing
Models that provide interfaces to resizable data structures can provide implementations of
insertRows()
,removeRows()
,insertColumns()
,andremoveColumns()
. When implementing these functions, it is important to notify any connected views about changes to the model's dimensions both before and after they occur:- An
insertRows()
implementation must callbeginInsertRows()
before inserting new rows into the data structure, andendInsertRows()
immediately afterwards.
void addValue() { Record r = { QDateTime::currentDateTime().toString(), QString::number(qrand() % 1000) }; beginInsertRows(QModelIndex(),mRecords.size(),mRecords.size()); mRecords << r; endInsertRows(); qDebug() << "Added record" << r.date << r.value; }
P.S.
Make your model go through the model test there's a couple of points that should get triggered by that test in your model - An