[Предыдущая: Модели-посредники] [Содержание] Создание собственных моделей
ВведениеПодклассы моделей необходимо обеспечить реализациями многих виртуальных функций, объявленных в базовом классе QAbstractItemModel. Некоторое количество этих функций, которые необходимо реализовать, зависят от типа модели - предоставляет ли представление с простым списком, таблицей или сложной иерархией элементов. Унаследованные от QAbstractListModel и QAbstractTableModel модели могут получить преимущество от стандартных реализаций функций, предоставляемых этими классами. Модели, которые предоставляют элементы данных в древовидных структурах, обязаны предоставить реализации для многих виртуальных функций QAbstractItemModel. Функции, которые необходимо реализовать в подклассе модели, можно разделить на три группы:
Для получения дополнительной информации смотрите главу "Item View Classes" в книге "C++ GUI Programming with Qt 4". Обработка элементов данныхМодели могут варьировать уровень доступа к предоставляемым ими данным: Они могут быть простыми компонентами только для чтения, другие модели могут обеспечивать операции изменения размера, а другие могут разрешить редактировать элементы. Доступ только для чтенияЧтобы обеспечить доступ к предоставляемым моделью данным только для чтения, в подклассе модели должны быть реализованы следующие функции:
Эти четыре функции должны быть реализованы во всех видах моделей, включая модели списков (подклассы QAbstractListModel) и табличные модели (подклассы QAbstractTableModel). Кроме того, следующие функции должны быть реализованы в прямых наследниках QAbstractTableModel и QAbstractItemModel:
Редактируемые элементыРедактируемые модели разрешают модифицировать элементы данных, а также могут предоставить функции, разрешающие вставку и удаление строк и столбцов. Чтобы разрешить редактирование, должны быть корректно реализованы следующие функции:
Изменение размеров моделейВсе типы моделей могут поддерживать вставку и удаление строк. Табличные модели и иерархические модели могут также поддерживать вставку и удаление столбцов. Важно уведомить другие компоненты об изменениях в измерениях модели как до, так и после того как они произойдут. В результате, следующие функции могут быть реализованы для разрешения модели изменять размеры, но реализации должны гарантировать, что вызываются соответствующие функции для уведомления присоединенных представлений и делегатов:
Как правило, эти функции возвращают true если операция была успешной. Однако могут быть случаи, когда операция достигла успеха только частично; например, если строк может быть вставлено меньше указанного количества. В таких случаях модель должна возвращать false, чтобы, обозначив фатальную ошибку, дать возможность каким-нибудь присоединенным компонентам обработать ситуацию. Сигналы, испускаемые функциями, вызванными в реализациях API изменения размера, дают шанс присоединенным компонентам принять меры до того, как какие-либо данные станут недоступными. Инкапсуляция операций вставки и удаления с начальными и конечными функциями также дает возможность модели корректно управлять постоянными модельными индексами. Как правило, начальные и конечные функции способны уведомлять другие компоненты об изменениях в базовой структуре модели. Для более сложных изменений в структуре модели, приводящие возможно к преобразованию или сортировке данных, необходимо испустить сигнал layoutChanged(), чтобы заставить все присоединенные представления обновиться. Ленивое заполнение (Lazy Population) модели данныхЛенивое заполнение данных модели эффективно разрешает запросы информации о модели, отложенные до тех пор пока они фактически не понадобятся представлениям. Некоторые модели нуждаются в получении данных из удаленных источников или должны выполнять ресурсоемкие операции, чтобы получить информацию о способе организации данных. Так как представления обычно требуют так много информации, сколько возможно по порядку для правильного отображения данных модели, для уменьшения излишних откликов (follow-up) на запрашиваемые данные может быть полезным ограничить количество возвращаемой к ним информации. В иерархических моделях, где нахождение количества дочерних элементов заданного элемента является дорогостоящей операцией, полезно обеспечить, чтобы реализация rowCount() модели вызывалась только когда это необходимо. В таких случаях, функция hasChildren() может быть переопределена для предоставления представлениям экономного способа проверки наличия дочерних элементов и, в случае QTreeView, рисования соответствующего оформления их родительского элемента. Возвратит ли переопределенная функция hasChildren() true или false, для представлений нет необходимости вызывать rowCount(), чтобы узнать сколько имеется дочерних элементов. Например, QTreeView не нужно знать сколько имеется дочерних элементов, если родительский элемент не развернут для их показа. Если известно, что многие элементы имеют дочерние элементы, переопределение hasChildren() для безусловного возврата true является иногда полезным методом. Это гарантирует, что каждый элемент может позднее проверить наличие дочерних элементов при выполнении начального заполнения данных модели так быстро, как это возможно. Единственное неудобство - это то, что элементы без дочерних элементов в некоторых представлениях могут отображаться неправильно пока пользователь пытается просмотреть несуществующие дочерние элементы. Навигация и создание индекса моделиИерархические модели должны предоставить функции, которые могут вызываться представлениями для навигации в древовидных структурах, которые они отображают, и получения модельных индексов элементов. Родители и детиТак как структура, открытая представлениям, определяется базовой структурой данных, создание собственных модельных индексов для каждого подкласса модели обеспечивается реализацией следующих функций:
Обе приведенные выше функции используют фабрику функций createIndex() для генерации индексов, используемых другими компонентами. Для моделей является нормой снабжать эту функцию каким-нибудь уникальным идентификатором, чтобы гарантировать что модельный индекс может быть перепривязан к соответствующему элементу позднее. Поддержка перетаскивания (Drag and Drop) и обработка MIME-типовКлассы модель/представление поддерживают операции перетаскивания (drag and drop), предоставляя поведение по умолчанию, что подходит многим приложениям. Тем не менее, возможно также внести изменения в способ кодирования элементов во время операций перетаскивания, копируются ли они по умолчанию или перемещаются, и как они вставляются в существующие модели. Кроме того, классы вспомогательных представлений реализуют специализированное поведение, что отвечает ожиданиям существующих разработчиков. Раздел Вспомогательные представления предоставит обзор этого поведения. MIME данныеПо умолчанию, встроенные модели и представления используют внутренний MIME-тип (application/x-qabstractitemmodeldatalist) для передачи информации о модельных индексах. Это задает данные для списка элементов, содержащего номера строк и столбцов для каждого элемента и информацию о ролях, поддерживаемых для каждого элемента. Закодированные с использованием этого MIME-типа данные могут быть получены с помощью вызова QAbstractItemModel::mimeData() с QModelIndexList, содержащим элементы для преобразования в последовательную форму. При реализации поддержки перетаскивания в пользовательской модели, можно экспортировать элементы данных в специализированных форматах переопределив следующую функцию:
Для многих моделей полезно предоставить содержимое элементов в общем формате, представленном одним из MIME-типов, таких как text/plain или image/png. Обратите внимание на то, что изображения, цвета и документы HTML могут быть легко добавлены в объект QMimeData с помощью функций QMimeData::setImageData(), QMimeData::setColorData() и QMimeData::setHtml(). Получение отпускаемых данныхКогда операция перетаскивания выполняется в представлении, основная модель запрашивается для определения поддерживаемых ею типов операций и MIME-типов, которые она может принимать. Эта информация предоставляется функциями QAbstractItemModel::supportedDropActions() и QAbstractItemModel::mimeTypes(). Модели, которые не переопределяют реализации, предоставляемые QAbstractItemModel, поддерживают для элементов операции копирования и стандартный внутренний MIME-тип. Когда преобразованный в последовательную форму (serialized) элемент данных отпускается над представлением, данные вставляются в текущую модель, используя ее реализацию QAbstractItemModel::dropMimeData(). Стандартная реализация этой функции никогда не затирает какие-либо данные в модели; вместо этого она попытается вставить элементы данных либо на одном уровне с элементом, либо в качестве дочерних этого элемента. Чтобы воспользоваться реализацией по умолчанию QAbstractItemModel для встроенного MIME-типа, новые модели должны обеспечить переопределение следующих функций:
Чтобы принять другие формы данных эти функции должны быть переопределены:
Если реализация функции dropMimeData() изменяет измерения модели, вставляя или удаляя строки или столбцы, или же если элементы данных модифицировались, осторожность требует убедиться, что все соответствующие сигналы испущены. Полезно просто вызвать другие переопределенные функции в подклассе, такие как setData(), insertRows() и insertColumns(), чтобы убедиться, что модель ведет себя соответственно. Для того, чтобы убедиться что операции перетаскивания работают правильно, важно переопределить следующие функции, которые удаляют данные из модели: За дополнительной информацией о перетаскивании с представлениями элементов обратитесь к Использование перетаскивания (Drag and Drop) с представлениями элементов. Вспомогательные представленияВспомогательные представления (QListWidget, QTableWidget и QTreeWidget) замещают стандартную функциональность перетаскивания чтобы обеспечить меньшую гибкость, но более естественное поведение, подходящее многим приложениям. Например, так как наиболее распространено отпускание данных в ячейки QTableWidget с заменой имеющегося содержимого переданными данными, базовая модель будет устанавливать данные в элементы-приемник охотнее, чем вставлять в модель новые строки и строки. Для получения дополнительной информации о перетаскивании во вспомогательных представлениях смотрите Использование перетаскивания (Drag and Drop) с представлениями элементов. Оптимизация производительности для больших объемов данныхФункция canFetchMore() проверяет, содержит ли родитель дополнительные доступные данные и соответственно возвращает true или false. Функция fetchMore() извлекает данные, базирующиеся в указанном родителе. Обе этих функции могут комбинироваться, например, в запросе к базе данных содержать инкрементные данные для заполнения QAbstractItemModel. Мы переопределили canFetchMore() чтобы указать, если для извлечения имеется больше данных, и fetchMore() для заполнения модели по требованию. Другой пример будет динамически заполнять древовидные модели, в нем мы переопределяем fetchMore() когда ветвь дерева в древовидной модели является раскрытой. Замечание: Обе функции должны быть переопределены, так как стандартная реализация canFetchMore() возвращает false, а fetchMore() ничего не делает. [Предыдущая: Модели-посредники] [Содержание]
|
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |