QT 4: программирование GUI на С++
Шрифт:
Рис. 10.1. Архитектура модель/представление в Qt.
В Qt используется вдохновленная подходом MVC архитектура модель/представление. Здесь модель имеет такие же функции, как и в классическом методе MVC. Но вместо контроллера в Qt используется немного другое понятие: делегат (delegate). Делегат обеспечивает более тонкое управление воспроизведением и редактированием элементов. Для каждого типа представления в Qt предусмотрен делегат по умолчанию. Для большинства приложений вполне достаточно пользоваться таким делегатом, поэтому обычно нам не приходится заботиться о нем.
Применяя архитектуру Qt модель/представление, мы можем использовать
Во многих случаях пользователю необходимо работать только с относительно небольшим количеством элементов. В такой ситуации, как правило, мы можем использовать удобные классы Qt по отображению элементов (QListWidget, QTableWidget и QTreeWidget), непосредственно заполняя все элементы значениями. Эти классы работают подобно классам отображения элементов в предыдущих версиях Qt. Они хранят свои данные в «элементах» (например, QTableWidget содержит элементы QTableWidgetltem). При реализации этих удобных классов используются пользовательские модели, обеспечивающие появление требуемых элементов в представлениях.
Рис. 10.2. Одна модель может обслуживать несколько представлений.
При использовании больших наборов данных часто оказывается недопустимым дублирование данных. В этих случаях мы можем применять классы Qt по отображению элементов (QListView, QTableView и QTreeView) в сочетании с моделью данных, которой может быть как пользовательская модель, так и одна из заранее определенных в Qt моделей. Например, если набор данных хранится в базе данных, мы можем использовать QTableView в сочетании с QSqlTableModel.
Применение удобных классов отображения элементов
Удобные Qt—подклассы отображения элементов обычно использовать проще, чем определять пользовательскую модель, и они особенно удобны, когда разделение модели и представления нам не дает преимущества. Мы использовали этот подход в главе 4 , когда создавали подклассы QTableWidget и QTableWidgetItem для реализации функциональности электронной таблицы.
В данном разделе мы покажем, как можно применять удобные классы отображения элементов для вывода на экран элементов. В первом примере приводится используемый только для чтения виджет QListWidget, во втором примере — редактируемый QTableWidget и в третьем примере — используемый только для чтения QTreeWidget.
Мы начинаем с простого диалогового окна, которое позволяет пользователю выбрать из списка символ, используемый в блок-схемах программ. Каждый элемент состоит из пиктограммы, текста и уникального идентификатора.
Сначала покажем фрагмент заголовочного файла диалогового окна:
Рис. 10.3. Приложение Выбор символа блок—схемы (Flowchart Symbol Picker).
При создании диалогового окна мы должны передать его конструктору ассоциативный массив QMap<int, QString>, и после выполнения конструктора мы можем получить идентификатор выбранного элемента (или —1, если пользователь ничего не выбрал), вызывая selectedId.
Мы инициализируем id (идентификатор последнего выбранного элемента) значением —1. Затем мы конструируем QListWidget — удобный виджет отображения элементов. Мы проходим в цикле по всем элементам ассоциативного массива символов блок—схемы symbolMap и для каждого создаем объект QListWidgetItem. Конструктор QListWidgetItem принимает выводимую на экран строку QString и родительский виджет QListWidget.
Затем задаем пиктограмму элемента и вызываем setData для сохранения в QListWidgetItem идентификатора элемента. Закрытая функция iconForSymbol возвращает QIcon для заданного имени символа.
QListWidgetItem может выступать в разных ролях, каждой из которых соответствует определенный объект QVariant. Самыми распространенными ролями являются Qt::DisplayRole, Qt::EditRole и Qt::IconRole, и для них предусмотрены удобные функции по установке и получению их значений (setText, setIcon), но имеется также несколько других ролей. Кроме того, мы можем определить пользовательские роли, задавая числовое значение, равное или большее, чем Qt::UserRole. В нашем примере мы используем Qt::UserRole при сохранении идентификатора каждого элемента.
В непоказанной части конструктора создаются кнопки, выполняется компоновка виджетов и задается заголовок окна.