Обновление QTreeView при изменении данных

380
06 января 2017, 10:18

Есть класс, наследованный от 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());
}

Вызывается этот метод при нажатии кнопки после добавления новой записи в БД. Но дерево не перерисовывается.

Answer 1

Когда у вас добавляются строки в модель нужно использовать методы beginInsertRows и endInsertRows.

Добавление строки в конец будет выглядеть примерно так:

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

Если изменилась вся модель, нужны методы beginResetModel и endResetModel

Полное обновление модели выглядит так:

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

Аналогичные пары begin/end методов есть и для других случаев жизни ознакомиться с ними можете здесь

READ ALSO
Оптимизация вложенного SQL запроса

Оптимизация вложенного SQL запроса

Всем привет и с наступившим Новым Годом!

349
Получить следующую запись по ID

Получить следующую запись по ID

Известен idЕсть таблица где Id, title

285
Java - создание графического интерфейса [требует правки]

Java - создание графического интерфейса [требует правки]

Учусь создавать приложения на JavaВозник такой вопрос: на чем лучше создавать графический интерфейс? Делал 2 пробных проекта с GUI, используя...

352