crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Архитектура Модель-Представление, Особенности реализации архитектуры MVC в Qt
vo.borodin
  опции профиля:
сообщение 31.3.2014, 8:14
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 26.3.2014
Пользователь №: 4088

Спасибо сказали: 0 раз(а)




Репутация:   0  


В последнее время отошел от C++, но сейчас хочу возвратить навыки по нему. Реализация архитектуры Модель-Представление в Qt - тема интересная и сложная, хочу в ней разобраться. Есть много непонятных моментов и фундаментальных вопросов. Обо всём по порядку:
1) Класс QAbstractItemModel, как я понимаю, представляет собой самый общий интерфейс для модели, представляющей собой обертку над древовидной структурой данных. Есть корневой элемент данных, у корневого элемента есть потомки. Каждый из потомков является (или может являться) верхним левым элементом в некоей таблице элементов. Каждый из элементов в этой таблице сам может иметь потомков, и т. д. Так вот, я правильно понимаю, что модельный индекс QModelIndex - это некий объект, который ставится в соответствие каждому элементу данных в этой структуре и по которому можно этот элемент найти?
2) Лейтмотивом создания архитектуры MVC являлось отделение данных от способа их представления. Допустим, моё представление должно на основе данных в моей модели что-то нарисовать. Представление, я так понимаю, доступается до данных в модели через модельные индексы QModelIndex. Так вот, должно ли представление знать о способе организации данных в модели? Или смысл следующий: для одной модели мы можем создать несколько представлений, каждое из которых знает структуру данных в модели и отображает данные по-своему?
3) В чем суть делегатов? Должны ли они участвовать в отображении данных или только в обработке действий пользователя?
4) Допустим, в моей модели есть древовидная структура данных, в которой узлы дерева разных уровней представляются разными пользовательскими классами. Т. е. примерно так:
class E
{
private:
    // Некоторые собственные данные класса
    int m_e1;
    double m_e2;
};

class D
{
private:
    // Некоторые собственные данные класса
    QVector<E> vectorE;
};

class C
{
private:
   // Некоторые собственные данные класса
   bool m_c1;
   double m_c2;
   double m_c3;
};

class B
{
private:
    // Некоторые собственные данные класса
    C m_b1;
    int m_b2;
    QVector<D> vectorD;
};

class A: public QAbstractItemModel
{
private:
    QVector<B> vectorB;
};


Возвращать QModelIndex должен метод index() в классе A. Но как в этом методе организовать генерацию индексов для объектов классов B, C, D, E и содержащихся в них данных?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 31.3.2014, 9:12
Сообщение #2


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


1. Да, QModelIndex ставится в соответствие каждому элементу. Он кроме i и j ещё имеет третью координату parent. Этого достаточно, чтобы добраться до любого элемента.
2. Так вот, должно ли представление знать о способе организации данных в модели? Ну, если учесть, что есть несколько потомков от QAbstractItemView, легко предположить, что представление считает, что оно имеет представление о модели. Если вы предложите QTableView отобразить дерево, думаю ничего хорошего не получится, отобразится максимум один столбец, потому что QTableView не предназначено для отображения дерева
3) "В чем суть делегатов? Должны ли они участвовать в отображении данных или только в обработке действий пользователя?" Посмотрите на методы класса: он может отрисовывать данные элемента, и предоставляет виджет-редактор для редактирования данных элемента.
4. определите во всех классах метод index() + рекурсия, и будет вам счастье. Вот примеры древовидной модели:
http://qt-project.org/doc/qt-5.0/qtwidgets...etreemodel.html
http://qt-project.org/doc/qt-5.0/qtwidgets...etreemodel.html
И ещё, читайте внимательно обзорную статью по MVC, там всё описано, просто не сразу осознаётся весь принцип. Но после разборки пары примеров и собственных опытов всё становится на свои места.

Сообщение отредактировал Анна - 31.3.2014, 9:13
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.4.2014, 18:49
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(vo.borodin @ 31.3.2014, 10:14) *
Так вот, должно ли представление знать о способе организации данных в модели?
да, оно должно оперировать модельными индексами (координатами данных) для доступа к данным и ролями модели (альтернативные данные по этим же координатам)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.4.2014, 20:04
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Также соит отметить что есть ещё одна вспомогательная модель - Модель выделения (SelectionModel), посмотри пример
%QTDIR%\examples\itemviews\chart

Цитата(vo.borodin @ 31.3.2014, 10:14) *
Но как в этом методе организовать генерацию индексов для объектов классов B, C, D, E и содержащихся в них данных?
Связать индекс с реальными данными можно с помощью метода:
QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) const [protected]

Посмотри пример "Simple Tree Model"
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
vo.borodin
  опции профиля:
сообщение 11.6.2014, 19:21
Сообщение #5


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 26.3.2014
Пользователь №: 4088

Спасибо сказали: 0 раз(а)




Репутация:   0  


Всем спасибо за ответы. У меня в ходе разработки моего проекта появился ещё один вопрос относительно модели/представления в Qt. Допустим, мы находимся в рамках того кода, который я привёл выше. По определенному действию (например, нажатию на пункт главного меню) мне нужно добавить новый элемент в вектор vectorB (член данных класса A), а представление должно отреагировать на это добавление созданием нового виджета (скажем, созданием новой вкладки в объекте класса QTabWidget). Как это всё организовать? Начальные этапы понятны: при нажатии на пункт главного меню я вызываю у модели метод insertRow, передав ему такие параметры, чтобы добавился элемент в корневом классе иерархии, т.е. классе A; а что делать дальше?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 7.11.2024, 3:17