There is a class inherited from QAbstractItemModel and QTreeView based on this model. The model is based on a table of the form id/name/parent_id taken from the MySQL . This table is stored in the model constructor in the QList<TreeItem> list , where TreeItem is the structure that contains the fields id , name , parent_id . There is a button, by pressing which a new entry is added to the database. How can I implement automatic tree redrawing when adding a new record to the database? Model code:

 TreeModel::TreeModel(QWidget *parent) : QAbstractItemModel(parent) { CatProductsBL bl; list = bl.getTreeData(); } QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED (column); uint parent_id = parent.isValid() ? parent.internalId() : 0; QList<TreeItem> children; for(int i=0; i<list.size(); i++){ if(list.at(i).parent_id==parent_id) children.append(list.at(i)); } int id = children.at(row).id; return createIndex(row, 0, id); } QModelIndex TreeModel::parent(const QModelIndex &child) const { //Получаем id родителя. uint parent_id; for(int i=0; i<list.size(); i++){ if(list.at(i).id==child.internalId()) parent_id = list.at(i).parent_id; } if(parent_id==0) return QModelIndex(); //Получаем место родителя в списке родителей того же уровня (row). //код родителя родителя uint parentOfParent_id; for(int i=0; i<list.size(); i++){ if(list.at(i).id==parent_id) parentOfParent_id = list.at(i).parent_id; } //список всех родителей, имеющих того же прародителя QList<TreeItem> parents; for(int i=0; i<list.size(); i++){ if(list.at(i).parent_id==parentOfParent_id) parents.append(list.at(i)); } //определяем позицию row среди всех предков uint row; for(int i=0; i<parents.size(); i++){ if(parents.at(i).id==parent_id) row=i; } return createIndex(row, 0, parent_id); } int TreeModel::rowCount(const QModelIndex &parent) const { int childCount=0; for(int i=0; i<list.size(); i++){ if(list.at(i).parent_id==parent.internalId()) childCount++; } return childCount; } int TreeModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 1; } QVariant TreeModel::data(const QModelIndex &index, int role) const { if(role==Qt::DisplayRole){ for(int i=0; i<list.size(); i++){ if(list.at(i).id==index.internalId()) return list.at(i).name; } } return QVariant(); } 

I read about emit dataChanged (). I tried to add the following code to the model class:

 void TreeModel::updateTree() { list.clear(); CatProductsBL bl; list = bl.getTreeData(); emit dataChanged(QModelIndex(), QModelIndex()); } 

This method is called when the button is pressed after adding a new record to the database. But the tree does not redraw.

  • Call him refresh or repaint - nick_n_a
  • Who, QTreeView? repaint does not help. There is no refresh method for the view. - Artik
  • Windows "caches" redraw. Make InvalidRect(окно_handle, rect=null, true) it will reset the cache, and then repaint . In WINAPI it helps, I did not write qt ... - nick_n_a
  • Sorry, but not that. - Artik
  • It works if instead of dataChanged (QModelIndex (), QModelIndex ()) emit layoutChanged (). I do not quite understand the differences between these two methods. - Artik

1 answer 1

When you add rows to the model, you need to use the beginInsertRows and endInsertRows methods .

Adding a line to the end will look something like this:

 void Model::addRow(){ int r = rowCount(); beginInsertRows(QModelIndex(), r, r); // Добавляем одну строку в конец endInsertRows(); } 

If the whole model has changed, the beginResetModel and endResetModel methods are needed .

A complete update of the model looks like this:

 void Model::reset(){ beginResetModel(); // Перечитываем все данные из бд endResetModel(); } 

Similar pairs of begin / end methods are available for other cases of life here.

  • Thanks, begin / endResetModel pair helped! I added it to the void TreeModel :: updateTree () method, between them I wrote the update code of the QList list, on the basis of which the model is built. It turns out now you do not need to do emit layoutChanged ()? And in what cases are emit LayoutChanged () and emit dataChanged () used then? - Artik
  • 2
    dataChanged should be used if the data has changed in an existing cell (editing). I can’t say anything about layoutChanged , since it was entered into qt5, and I work with qt4. As I understood from the reference, this signal is needed when the order of the rows / columns changes, but the data itself does not change (sorting). - yrHeTaTeJlb