QT 4: программирование GUI на С++
Шрифт:
Рис. 10.11. Дерево наследования для абстрактных классов моделей.
Для модели таблицы, используемой только для чтения, мы должны переопределить три функции: rowCount, columnCount и data. В данном случае мы также переопределили функцию headerData и обеспечили функцию инициализации данных (setCurrencyMap).
В
В этой табличной модели счетчики строк и столбцов представляют собой номера валют в ассоциативном массиве валют. Параметр parent не имеет смысла в модели таблицы; он здесь указан, потому что rowCount и columnCount наследуются от более обобщенного базового класса QAbstractItemModel, поддерживающего иерархические структуры.
Функция data возвращает значение любой одной роли элемента. Элемент определяется индексом QModelIndex. В модели таблицы представляют интерес такие компоненты QModelIndex, как номер строки и номер столбца, получить доступ к которым можно с помощью функций row и column.
Если используется роль Qt::TextAlignmentRole, мы возвращаем значение, подходящее для выравнивания чисел. Если используется роль Qt::DisplayRole, мы находим значение каждой валюты и вычисляем курс обмена.
Мы могли бы возвращать рассчитанное значение типа double, но тогда нам пришлось бы контролировать количество позиций после десятичной точки при отображении числа (если мы не используем пользовательский делегат). Вместо этого мы возвращаем значение в виде строки, отформатированной
нужным нам образом.Функция headerData вызывается представлением для пополнения своих горизонтальных и вертикальных заголовков. Параметр section содержит номер строки или столбца (в зависимости от ориентации). Поскольку строки и столбцы содержат одинаковые коды валют, нам не надо заботиться об ориентации, а просто вернуть код валюты для заданного значения section.
Вызывающая программа может изменить набор валют, используя функцию setCurrencyMap. Вызов QAbstractItemModel::reset указывает любому представлению, что все данные в используемой модели недействительны; это вынуждает их запросить свежие данные для тех элементов, которые видны на экране.
Функция currencyAt возвращает ключ (код валюты), который находится по указанному смещению в ассоциативном массиве валют. Мы используем итератор в стиле STL для поиска элемента и вызываем для него функцию key.
Как мы только что могли убедиться, нетрудно создавать модели, используемые только для чтения, и при определенном характере исходных данных в хорошо спроектированной модели в принципе можно сэкономить память и увеличить быстродействие. В следующем примере приложения Города (Cities) также используется табличная модель, но на этот раз все данные вводятся пользователем.
Это приложение используется для хранения расстояний между любыми двумя городами. Как и в предыдущем примере, мы могли бы просто использовать табличный виджет QTableWidget и хранить один элемент для каждой пары городов. Однако пользовательская модель могла бы быть более эффективной, потому что расстояние от любого города А до любого другого города В не зависит от того, будем ли мы путешествовать от А до В или от В до А, поэтому элементы с одной стороны от главной диагонали получаются путем зеркального отражения другой.
Для сравнения пользовательской модели с простой таблицей предположим, что у нас имеется три города: А, В и С. Для обеспечения всех сочетаний нам пришлось бы хранить девять значений. В аккуратно спроектированной модели потребовалось бы только три элемента: (А, В), (A, С) и (В, С).
Рис. 10.12. Приложение Города.
Ниже показано, как мы настраиваем и используем модель: