Russian Qt Forum
Март 28, 2024, 16:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как уведомить TreeView или TreeModel отобразить/обновить новые данные?  (Прочитано 8052 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Декабрь 01, 2010, 12:58 »

Доброго всем времени.

Стоит задача, используя MVC в QTreeView отображать древовидную структуру данных от источника данных.

Вступление.
Источник данных - это отдельный класс, который имеет приватный указатель на древовидную структуру данных, а также метод который возвращает этот приватный указатель, т.е.:
Код:
class RootNode;
class Core : public QObject
{
    Q_OBJECT

public:
    Core(QObject *parent = 0);
    RootNode *rootNode(); //<== Метод который возвращает приватный указатель на корневую ноду.
    /*
     тут какие-то другие методы для управлениями дочерними узлами (добавления, удаления, заполнения данными) корневого узла
    */

private:
    RootNode *m_rootNode; //<== Собственно сам указатель на корневую ноду.
};

Класс RootNode - реализован аналогично классу из примеров : examples\itemviews\simpletreemodel\treeitem.h

Теперь, имею модель дерева в конструктор которой передается указатель на корневую ноду core->rootNode() :
Код:
class RootNode;
class CoreTreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    CoreTreeModel(RootNode *rootNode, QObject *parent = 0);
    ~CoreTreeModel();

    /* тут определен стандартный минимальный набор методов модели
    */

private:
    RootNode *rootNode;
};


Также имею класс наследованный от QTreeView в который передаю указатель на мою модель.

Проблема.
Запускаю приложение, в процессе работы которого выполняется некий алгоритм,  который производит добавление, изменение данных в корневом дереве класса Core.
Необходимо, чтобы все изменения произведенные в классе Core автоматически отображались в QTreeView .

Например,  алгоритм по таймеру, каждые 5 сек создает в какие-то дочерние ноды/подноды в Core и, если QTreeView в данный момент раскрыта родительская нода (в которую добавляются дети), то в ней в этот момент добавленные дети не отображаются! Отобразятся только после того как я жмакну в QTreeView на значки " (-) / (+) " этой родительской ноды.

Подскажите, как можно реализовать всё это дело?
Или, может быть, я выбрал неудачную концепцию отображения узлов?

ЗЫ: Я попробовал запустить пример: \examples\itemviews\dirview\ - но там тоже аналогичное поведение, т.е. если я раскрываю любую директорию с файлами, и после этого создаю в ней (с помощью проводника или тотал коммандера к примеру) другие директории или файлы - то они не отображаются в примере с QDirModel.

Вот такая у мена проблема. Буду рад любой помощи. Может быть, кто-то уже красиво решил подобную задачу и поделится? Улыбающийся
« Последнее редактирование: Декабрь 01, 2010, 13:01 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
crossly
Гость
« Ответ #1 : Декабрь 01, 2010, 13:50 »

Код:
void dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )
void rowsInserted ( const QModelIndex & parent, int start, int end )
void rowsRemoved ( const QModelIndex & parent, int start, int end )

эти сигналы автоматически коннектятся во вью при установке модели....
Записан
UVV
Гость
« Ответ #2 : Декабрь 01, 2010, 13:52 »

... который производит добавление, изменение данных в корневом дереве класса Core. ...

Каким образом это реализовано?
Вызываются ли соответствующие функции beginInsertRows()/endInsertRows() и emit dataChanged() внутри модели?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Декабрь 01, 2010, 13:59 »

Цитировать
эти сигналы автоматически коннектятся во вью при установке модели....
Да, это то всё так если я дергаю методы removeRows(), setData() и т.п. самой модели.
Но у меня данные в Core меняются независимо, т.е. не методы модели их изменяют!

На ум приходит только единственный выход - это емиттить из Core в модель сигнал о том что данные изменились, при этом модель будет дёргать метод reset().
« Последнее редактирование: Декабрь 01, 2010, 14:03 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Декабрь 01, 2010, 14:03 »

Цитировать
Каким образом это реализовано?
Вызываются ли соответствующие функции beginInsertRows()/endInsertRows() и emit dataChanged() внутри модели?
Допустим в Core тикает таимер и по каждому его срабатыванию добавляются дети в какого то родителя.. и все.
Модель же при этом имеет только указатель на корневой узел, который находится в Core.
Записан

ArchLinux x86_64 / Win10 64 bit
UVV
Гость
« Ответ #5 : Декабрь 01, 2010, 14:46 »

Допустим в Core тикает таимер и по каждому его срабатыванию добавляются дети в какого то родителя.. и все.
Модель же при этом имеет только указатель на корневой узел, который находится в Core.
Неправильно, данные должны изменяться из модели с вызовом соответствующих функций.
Записан
trot
Гость
« Ответ #6 : Декабрь 01, 2010, 22:28 »

В традиционном MVC издателем является модель, а treeview подписчиком. В вашем случае издателем выступает core, а подписчиком модель и далее по цепочке. Поэтому вы сами нашли правильное решение

Цитировать
На ум приходит только единственный выход - это емиттить из Core в модель сигнал о том что данные изменились, при этом модель будет дёргать метод reset().

Ну или самому реализовывать механизм оповещения своих подписчиков.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Декабрь 02, 2010, 09:45 »

В традиционном MVC издателем является модель, а treeview подписчиком. В вашем случае издателем выступает core, а подписчиком модель и далее по цепочке. Поэтому вы сами нашли правильное решение

Цитировать
На ум приходит только единственный выход - это емиттить из Core в модель сигнал о том что данные изменились, при этом модель будет дёргать метод reset().

Ну или самому реализовывать механизм оповещения своих подписчиков.

Ох, не думал что всё оно так сложно...
Т.е. в общем случае, когда источник данных для модели может иметь любую структуру данных, и их мы хотим отобразить в виде дерева, то необходимо:
1. Внутри модели выполнить некое промежуточное хранилище данных (типа кеша), которое имеет tree-структуру (раз модель tree-типа).
2. Разработать какой-то свой API обмена данными между источником данных и моделью (например, используя механизм сигнал/слот для реализации некоего протокола обмена типа запрос/ответ, прием/квитанция и т.п.), при этом, модель, получив данные от источника должна их интерпретировать в определенном виде и определенным образом заполнить свой внутренний "кеш", для того, чтобы QTreeView (или любой другой) смог правильно отобразить данные.

Т.е. в общем виде схема будет такая, которую я прицепил в аттач?
Я правильно представляю всю глубину глубин?
Записан

ArchLinux x86_64 / Win10 64 bit
trot
Гость
« Ответ #8 : Декабрь 02, 2010, 22:29 »

Вы все правильно представляете.
На первый взгляд это кажется, что сложно. На самом деле это обыкновенная схема.
В источнике данных хранится, например результат sql запроса. В зависимости от вьюера он (источник данных) генерит ту или иную модель и эта модель привязывается к представлению. Данные инвариантны по отношению к представлению. К одному источнику данных можно привязать несколько вьюеров.  Кроме этого можно установить взаимосвязь между источниками данных. И тогда при выделении, например, в таблице какой-либо строчки, все зависимые представления перечитают свои данные.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.05 секунд. Запросов: 23.