html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Использование моделей в Qt

За последний год пришлось довольно много работать с Model/View фреймворком Qt. Приходилось как писать собственные модели, так и переделывать существующие. И вот, после созерцания очередного творения, решил представить общественности некоторые наработки.

Начнем с очевидного:

Не используйте виджеты

Все эти QTableWidget, QListWidget и QTreeWidget — не для вас.

Использование MVC фреймворка не составляет проблемы. В простейшем случае, можно использовать готовые модели, которые предоставляет Qt. Количество кода и его сложность при этом не растет, зато удается избежать всевозможных проблем роста. Разделение модели и отображения с самого начала позволяет с легкостью добавлять такие вещи как сортировка или фильтрация, не переписывая при этом половину кода.

Одни плюсы, а минусов, при этом, не замечено.

Используйте стандартный интерфейс работы с моделями

В общем, второй пункт вытекает напрямую из первого.

Посмотрите, какие функции предоставляет вам QAbstractItemModel. Только их и должен использовать ваш код, работающий с моделью. Этого интерфейса более чем достаточно. Никакой самодеятельноти. QStandardItemModel, например, содержит такую замечательную функцию, как
QStandardItem * item ( int row, int column = 0 ) const 

Не пользуйтесь ей. Все операции, в которых фигурируют Item-ы, должны быть только операциями заполнения модели данными.

Если вы собираетесь узнать текст элемента 5й строки 3го столбца, не надо писать
QString text = model->item(5, 3)->text();

Используйте для этого стандартный интерфейс моделей:
QModelIndex index = model->index(5, 3);
QString text = index.data(Qt::DisplayRole).toString();

Это сэкономит кучу усилий в дальнейшем, когда вы захотите поставить между моделью и компонентом отображения прокси-модель, выполняющую сортировку, и внезапно обнаружите, что она не содержит такой замечательной функции item().

Избегайте QStandardItemModel

Пожалуй, это самый сложный и неочевидный пункт для объяснения.

Модель QStandardItemModel предоставляет универсальный интерфейс, так что с его помощью можно достаточно быстро сделать какую угодно структуру представления данных.

Однако есть в ее использовании и существенные недостатки.

Во-первых, Qt предоставляет несколько готовых простых моделей для некоторых случаев: QStringListModel, QDirModel, QFileSystemModel, QSqlQueryModel с ее родственниками — к вашим услугам!

К сожалению, в большинстве случаев они не очень подходят. Что же, разрабатывать собственные модели для каждого случая?

Действительно, на первый взгляд эта задача выглядит довольно сложной. На самом деле все не так страшно. Но перед тем, как перейти к практической части написания модели, давайте рассмотрим несколько концептуальных вопросов.

Как выглядит работа с данными при использовании QStandardItemModel?
  • Получаем данные из внешнего источника.
  • Заполняем модель полученными данными.
  • После того, как этот процесс завершен, можно отобразить модель.
  • Чтобы синхронизировать изменения, внесенные пользователем, подписываемся на сигналы (например, itemChanged())

Выглядит не так уж плохо? Не тут-то было!

Во-первых, если объем данных большой, то построение модели займет достаточно много времени. Более того, поскольку модель должна быть готова полностью до того, как мы сможем показать ее пользователю, придется прочитать все данные.

Во-вторых, мы получаем, фактически, две модели данных – одна – источник данных и вторая – стандартная модель Qt. И эти модели нужно синхронизировать. Эта задача не такая простая, как кажется на первый взгляд.

К примеру, пользователь изменил некоторое значение в ячейке. Мы пробуем записать это значение в источник, но ничего не выходит (например, с источником данных потеряна связь). Теперь необходимо вернуть старое значение, чтобы не нарушить согласованность данных. Но его еще надо откуда-то взять! То есть, приходится хранить еще один, резервный, набор данных.

Фактически, все многообразие возникающих проблем проистекает из одного печального факта: как только вы начинаете использовать стандартную модель, вы больше не контролируете ваши данные. Вы встречаетесь уже со случившимися фактами, вы вынуждены исправлять ошибки, внесенные в структуру ваших данных, но вы не можете избежать их. Вы не можете навесить какие либо ограничения целостности.

Поэтому я предлагаю отказаться от стандартной модели для большинства случаев. На самом деле, вам не нужно даже разрабатывать свою модель. Потому что ваши данные – это и есть ваша модель. Она уже готова. Вам нужно только написать тонкую обертку, которая согласовывала бы интерфейс вашей модели с интерфейсом моделей Qt MVC.

В этом вам помогут стандартные заготовки Qt: QAbstractListModel, QAbstractTableModel. Адаптация их для конкретных случаев, как правило, очень проста. Вам нужно реализовать всего несколько функций, и их реализация, обычно, тривиальна.

При этом вы разом избавляетесь от множетва проблем.
  • Не нужно «строить» модель. Модель уже готова после того, как создана. Для того, чтобы начать с ней работать, вам даже не нужны данные. Вам необходима только метаинформация, которую вы внесли в модель еще на этапе разработки. Все остальное вам понадобится только тогда, когда об этом спросят.
    При этом, если количество данных в модели велико, то большую часть их не спросят, вероятно, никогда.
  • Вы можете использовать все возможность технологии Qt MVC, вроде динамической подгрузки данных или быстрого перемещения строк.
  • Вы можете наложить ограничения целостности на ваши данные и не дать пользователю их разрушить.
  • Вы можете использовать автоматически вычислимые данные и значения по умолчанию.
    Просто попробуйте сделать с использованием QStandardItemModel так, чтобы ячейки с нечетными значениями отображались с зеленым цветом фона, а ячейки с четными значениями – с красным. Данные ячеек, естественно, могут быть изменены пользователем.

Совет напоследок


Как вы думаете, какая функция модели будет вызываться чаще всего? Правильно, это функция index().Она вызывается действительно часто. Нет, не так часто, как вы подумали. На порядок чаще. А функция index(), скорее всего, будет вызывать функции rowCount() и columnCount(). Эта тройка должна работать быстро, особенно если данных в модели будет много.

А вот запрос на актуализацию данных, вызов data(), будет происходить только тогда, когда эти данные действительно нужны. Например, для того, чтобы показать их пользователю. Если часть данных не видна в окне, то и запрашиваться она не будет.

P.S. Если интересно, могу рассказать о чем угодно подробнее по теме работы с моделями. Предложения принимаются.

По просьбам трудящихся, убрал КДПВ.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

1

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции