![]() |
Главная · Все классы · Основные классы · Классы по группам · Модули · Функции | ![]() |
[Предыдущая: Классы-контейнеры Tulip] [Начало] [Следующая: Система рисования Arthur]
Классы Interview обеспечивают структуру модель/представление для приложений, базирующихся на этом известном шаблоне проектирования модель-представление-контроллер (Model-View-Controller). В данном документе мы опишем архитектуру модель/представление Qt, представим несколько примеров и продемонстрируем усовершенствования классов представления элементов по сравнению с Qt 3.
Архитектура модель/представление - это разновидность шаблона проектирования модель-представление-контроллер (Model-View-Controller, MVC), пришедшей из Smalltalk, часто используемый при создании пользовательских интерфейсов.
В архитектуре модель/представление представление и структура данных объединены. Это все еще отделяет способ хранения данных от способа их представления пользователю, но обеспечивает простую структуру, основанную на тех же принципах. Данное разделение дает возможность показать пользователю одни и те же данных в различных представлениях и реализовать новые типы представлений без изменения базовой структуры данных.
Данные, вводимые пользователем, обрабатываются делегатами. Преимущество этого подхода состоит в том, что для каждый используемого типа данных он позволяет настраивать подходящее отображение и редактирование отдельных элементов данных.
![]() | Архитектура модель/представление Модель осуществляет соединение с источником данных, предоставляя необходимый интерфейс другим компонентам архитектуры. Характер связи зависит от типа источника данных и способа реализации модели. Из модели представление получает модельные индексы, являющиеся ссылками на элементы данных. Передавая модельные индексы модели, представление может получить элементы данных из источника данных. В стандартных представлениях делегат отображает элементы данных. Если элемент редактируемый, делегат связывается с моделью непосредственно используя модельные индексы. |
На фундаментальном уровне классы Interview определяют интерфейсы и общие функциональные возможности для моделей, представлений и делегатов. Все реализованные компоненты являются подклассами QAbstractItemModel, QAbstractItemView или QAbstractItemDelegate. Использование общего API обеспечивает возможность взаимодействия между компонентами.
Interview предоставляет готовые для использования реализации представлений для виджетов таблицы, дерева и списка: QTableView, QTreeView и QListView. Эти стандартные представления, подходящие для отображения наиболее распространенных типов структур информации, используемых в приложениях, могут использоваться с готовыми моделями поставляемыми с Qt:
Обе предоставляемые специализированные абстрактные модели могут быть расширены и послужить базовыми классами (смотрите примеры в Программирование модель/представление):
Операции над элементами, например фильтрация и сортировка, обрабатываются моделями-посредниками, которые позволяют отображать обработанные данные без необходимости копировать или изменять данные, полученные от модели-источника. Interview предоставляет класс QSortFilterProxyModel, позволяющий отсортировать и отфильтровать элементы данных из модели-источника до того, как они будут переданы представлению.
Разработчики, предпочитающие обычные виджеты списка, дерева и таблицы, могут найти полезными QListWidget, QTreeWidget и QTableWidget. Они предоставляют облегченный интерфейс для представлений не требующий знания основ архитектуры модель/представление.
Для получения детальных сведений об использовании классов модель/представление, смотрите документ Программирование модель/представление.
Для получения информации о моделях баз данных Qt 4, также смотрите документ GUI работы с базами данных.
Чтобы проиллюстрировать использование классов модель/представление, мы представляем два примера, демонстрирующих различные аспекты использования архитектуры модель/представление.
В данном примере мы показываем содержимое модели, используя два различных представления и разделяем между ними выбор элементов. Мы будем использовать модель QDirModel, предоставляемую Qt, так как она потребует минимума настройки и предоставит данные для представлений.
Функция main() данного примера демонстрирует все принципы, применяемые для настройки модели и двух представлений. Мы также разделяем выбор между двумя представлениями:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QSplitter *splitter = new QSplitter; QDirModel *model = new QDirModel; QTreeView *tree = new QTreeView(splitter); tree->setModel(model); tree->setRootIndex(model->index(QDir::currentPath())); QListView *list = new QListView(splitter); list->setModel(model); list->setRootIndex(model->index(QDir::currentPath())); QItemSelectionModel *selection = new QItemSelectionModel(model); tree->setSelectionModel(selection); list->setSelectionModel(selection); splitter->setWindowTitle("Two views onto the same directory model"); splitter->show(); return app.exec(); }
В приведенной функции мы создаем модель каталога, чтобы показать содержимое каталога по умолчанию. Создаются два представления и для работы с ними предоставляется модель. По умолчанию, каждое представление создает и отображает свой собственный выбор элементов модели, поэтому мы явно создаем новый выбор, который разделяется между представлением дерева и представлением списка. В результате, изменение выбора в одном из этих представлений автоматически заставляет измениться выбор в другом представлении.
Архитектура модель/представление позволяет нам заменить в данном примере QDirModel на совершенно другую модель, получающую информацию от удаленного сервера или из базы данных.
В этом примере мы покажем элементы данных, полученные из пользовательской модели списка, используя стандартные предоставления. Собственная модель является подклассом QAbstractListModel и предоставляет реализацию основного набора функций.
Полное объявление нашей модели:
class StringListModel : public QAbstractListModel { Q_OBJECT public: StringListModel(const QStringList &strings, QObject *parent = 0) : QAbstractListModel(parent), stringList(strings) {} int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; private: QStringList stringList; };
При создании модель принимает список строк и по требованию передает их в представления. Так как это простая модель только для чтения, мы должны реализовать лишь несколько функций.
Базовой структурой данных, используемой для хранения строк, является QStringList. Так как модель отображает каждый элемент списка в отдельную строку модели, функция rowCount() очень проста:
int StringListModel::rowCount(const QModelIndex &parent) const { return stringList.count(); }
Функция data() возвращает элемент данных для каждого модельного индекса, предоставляемого представлением:
QVariant StringListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= stringList.size()) return QVariant(); if (role == Qt::DisplayRole) return stringList.at(index.row()); else return QVariant(); }
Функция data() возвращает значение типа QVariant, содержащее информацию, на которую ссылается модельный индекс. Элементы данных возвращаются представлению только если прошли все проверки переданного индекса; например, если представление задает неверный модельный индекс, модель указывает на это возвращая недействительный QVariant.
Вывод вертикальных или горизонтальных заголовков осуществляется функцией headerData(). В данной модели возвращаемое значение для этих элементов - это номер строки или столбца, находящегося в заголовке:
QVariant StringListModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) return QVariant(); if (orientation == Qt::Horizontal) return QString("Column %1").arg(section); else return QString("Row %1").arg(section); }
В данном примере мы приведем только часть функции main():
QStringList numbers; numbers << "One" << "Two" << "Three" << "Four" << "Five"; QAbstractItemModel *model = new StringListModel(numbers); ... QListView *view = new QListView; view->setWindowTitle("View onto a string list model"); view->setModel(model);
Мы создали список строк для использования с моделью и передаем его в модель при ее создании. Информация в списке строк сделана доступной представлению через нашу модель.
Этот пример показывает, как легко заполнять представления данными из простой модели. Стандартные модели и представления, разработанные для Qt 4, сделают этот процесс еще более легким, а вспомогательные виджеты обеспечат поддержку классического подхода на основе элементов данных.
Таблицы и классы представления элементов в Qt 3 реализовывались виджетами, которые и хранили данные, и представляли их пользователю. Эти классы проектировались легкими в работе и согласованными, но иногда их трудно было настраивать и расширять.
Эквивалентные классы в Qt 4 спроектированы так, чтобы быть расширяемыми при сохранении удобства в работе; использование архитектуры модель/представление гарантирует, что они стали более последовательны, чем их предшественники. Подведем итоги о предоставляемых классах представлений:
Так как модель берет на себя ответственность за предоставление элементов данных, а представление - за их отображение пользователю, нам не нужны классы элементов для отображения отдельных элементов. Делегаты обрабатывают отрисовку и редактирование данных, полученных от модели.
Qt продолжает предоставлять множество классических виджетов представлений элементов со знакомыми, основанными на элементах интерфейсами, которые не базируются на классах совместимости:
Каждый из вспомогательных классов имеет связанный с ним класс элементов: QListWidgetItem, QTreeWidgetItem и QTableWidgetItem являются эквивалентами в Qt 4 для QListBoxItem, QListViewItem и QTableItem из Qt 3 соответственно.
Элементы архитектуры модель/представление предусматривают и использование "как есть", и могут быть основой разработок программистов. Хотя такой подход может показаться чересчур сложным для простых приложений, он поощряет повторное использование компонентов.
[Предыдущая: Классы-контейнеры Tulip] [Начало] [Следующая: Система рисования Arthur]
Copyright © 2008 Trolltech | Торговые марки | Qt 4.3.5 |