Есть класс, наследованный от QAbstractItemModel
и QTreeView
на основе этой модели. Модель строится на основе таблицы вида id/name/parent_id
взятой из базы данных MySQL
. Эта таблица сохраняется в конструкторе модели в QList<TreeItem> list
, где TreeItem
- структура, которая содержит поля id
, name
, parent_id
. Есть кнопка, по нажатию которой в БД добавляется новая запись. Как можно реализовать автоматическую перерисовку дерева при добавлении новой записи в БД? Код модели:
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();
}
Почитал про emit dataChanged(). Попробовал добавить следующий код в класс модели:
void TreeModel::updateTree()
{
list.clear();
CatProductsBL bl;
list = bl.getTreeData();
emit dataChanged(QModelIndex(), QModelIndex());
}
Вызывается этот метод при нажатии кнопки после добавления новой записи в БД. Но дерево не перерисовывается.
Когда у вас добавляются строки в модель нужно использовать методы beginInsertRows и endInsertRows.
Добавление строки в конец будет выглядеть примерно так:
void Model::addRow(){
int r = rowCount();
beginInsertRows(QModelIndex(), r, r);
// Добавляем одну строку в конец
endInsertRows();
}
Если изменилась вся модель, нужны методы beginResetModel и endResetModel
Полное обновление модели выглядит так:
void Model::reset(){
beginResetModel();
// Перечитываем все данные из бд
endResetModel();
}
Аналогичные пары begin/end методов есть и для других случаев жизни ознакомиться с ними можете здесь
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Учусь создавать приложения на JavaВозник такой вопрос: на чем лучше создавать графический интерфейс? Делал 2 пробных проекта с GUI, используя...