Home · All Classes · Main Classes · Grouped Classes · Modules · Functions

[Предыдущая: Tulip - Классы-Контейнеры] [Начало] [Следующая: Система рисования Arthur]

Структура Interview

Классы Interview предоставляют структура модель/представление для приложений базирующихся на известном диспетчере дизайна Model-View-Controller. В данном документе мы опишем архитектуру модель/представление Qt, представим несколько примеров, и продемонстрируем усовершенствования элементов управления Qt 3.

Обзор Архитектуры Модель/Представление

Архитектура модель/представление - это разновидность модели дизайна Model-View-Controller (MVC), пришедшей из Smalltalk, часто используемой при создании пользовательских интерфейсов.

В архитектуре модель/представление представление и структура данных объединены. Это все еще отделяет способ хранения данных от способа их представления пользователю, но обеспечивает простую структуру основанную на тех же принципах. Данное разделение дает возможность показать пользователю одни и те же данных в различных видах без изменения структуры данных.

Данные вводимые пользователем обрабатываются так называемыми делегатами. Преимущество этого подхода в том, что позволяет делегировать обработку и редактирование данных вводимых пользователем обаботчикам способным это сделать в соответствии с их (данных) типом.

Архитектура модель/представление

Данная модель осуществляет соединение с источником данных, предоставляя необходимые интерфейсы другим компонентам архитектуры. Характер связи зависит от источника данных и способа использования модели.

Представление получает от модели индексы, являющиеся ссылками на элементы данных. Получая индексы от модели, представление может получить данные от источника.

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

Классы Модель/Представление

На фундаментальном уровне, классы Interview определяют интерфейсы и функциональные возможности для моделей, представлений и делегатов. Все реализованные компоненты являются подклассами QAbstractItemModel, QAbstractItemView или QAbstractItemDelegate. Использование стандартного API обеспечивает возможность взаимодействия между компонентами.

Interview предоставляет готовые для использования реализации представления для таблицы, дерева и списка виджетов: QTableView, QTreeView и QListView. Это стандартные представления подходящие для отображения наиболее распространенных типов структур информации используемых в приложениях, способные использовать модели поддерживаемые Qt:

Две специализированные абстрактные модели - могут быть использованы подклассами и расширениями (см. Model/View Программирование примеры):

Операции над элементами, вроде фильтрации и сортировки, выполняются посредниками модели, которые позволяют отображать обработанные данные без необходимости копировать или изменять данные, полученные от исходной модели. 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 3 содержали виджеты которые отвечали за хранение данных и представление их пользователю. При разработке этих классов реализовывалась легкость в работе и последовательность, но классы было трудно настраивать и расширять.

Эквивалентные классы в Qt 4 для того, чтобы быть расширяемыми при сохранении удобства в работе; использование архитектуры модель/представление гарантирует что они стали более последовательны, чем их предшественники. Представления могут быть получены из следующих элементов:

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

Qt продолжает предоставлять множество классических виджетов представлений со знакомыми основанными на записях интерфейсами на основанными на совместимых классах:

Каждому из классов-представлений соответствует класс записей: QListWidgetItem, QTreeWidgetItem и QTableWidgetItem в Qt 4 и в эквивалентных классах Qt 3 QListBoxItem, QListViewItem и QTableItem соответственно.

Элементы архитектуры модель/представление предусматривают и использование "как есть" и могут быть основой разработок программистов. Хотя такой подход кажется более громоздким для простых случаев, он поощряет повторное использование компонентов.

[Предыдущая: Tulip - классы-контейнеры] [Начало] [Следующая: Система рисования Arthur]


Copyright © 2005 Trolltech Trademarks
Qt 4.1.0
Hosted by uCoz