Qt:Документация 4.3.2/model-view-selection

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск
40px Внимание: Актуальная версия перевода документации находится здесь

__NOTOC__

Image:qt-logo.png

Главная · Все классы · Основные классы · Классы по группам · Модули · Функции

Image:trolltech-logo.png

[Предыдущая: Классы представлений ] [ Содержание ] [Следующая: Классы делегатов ]

Содержание

[править] Обработка выбора элементов в представлениях

[править] Концепции

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

Информация о выбранных элементах представления хранится в экземпляре класса QItemSelectionModel. Этот класс содержит свои собственные модельные индексы элементов независимо от представления. В связи с тем, что возможно использование нескольких представлений с одной моделью, можно разделить одну модель выбора между несколькими представлениями, позволив тем самым приложению отобразить одни и те же данные различными способами.

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

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

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

[править] Использование модели выбора

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

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

[править] Выбор элементов

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

     TableModel *model = new TableModel(8, 4, &app);
 
     QTableView *table = new QTableView(0);
     table->setModel(model);
 
     QItemSelectionModel *selectionModel = table->selectionModel();

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

     QModelIndex topLeft;
     QModelIndex bottomRight;
 
     topLeft = model->index(0, 0, QModelIndex());
     bottomRight = model->index(5, 2, QModelIndex());

Чтобы сделать эти элементы в модели выбранными и увидеть соответствующие изменения в табличном представлении, мы должны создать объект выбора и применить его к модели выбора:

     QItemSelection selection(topLeft, bottomRight);
     selectionModel->select(selection, QItemSelectionModel::Select);

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

Файл:Selected-items1.png

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

[править] Чтение состояния выбора

Модельные индексы, хранящиеся в модели выбора, могут быть прочитаны с помощью функции selectedIndexes(). Она возвращает несортированный список модельных индексов, который мы можем перебирать не задумываясь о том, к какой модели они относятся:

     QModelIndexList indexes = selectionModel->selectedIndexes();
     QModelIndex index;
 
     foreach(index, indexes) {
         QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
         model->setData(index, text);
     }

В вышеприведенном коде Qt для перебора индексов, возвращаемых моделью выбора, и изменения соответствующих им элементов используется удобная конструкция foreach.

Модель выбора испускает сигналы, сообщающие об изменениях в выборе. Они уведомляют другие компоненты как об изменениях модели выбора в целом, так и об изменениях элемента модели, имеющего в данным момент фокус. Мы можем соединить сигнал selectionChanged() со слотом и исследовать вновь выбранные элементы или элементы, которые при изменении выбора сделаны невыбранными. Слот вызывается с двумя объектами QItemSelection: один содержит список индексов, соответствующих выбранным элементам; другой содержит список индексов, соответствующих элементам, выбор которых был отменен.

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

 void MainWindow::updateSelection(const QItemSelection &selected,
     const QItemSelection &deselected)
 {
     QModelIndex index;
     QModelIndexList items = selected.indexes();
 
     foreach (index, items) {
         QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
         model->setData(index, text);
     }
 
     items = deselected.indexes();
 
     foreach (index, items)
         model->setData(index, "");
 }

Мы можем отследить изменение фокуса элементов внутри модели, соединив сигнал currentChanged() со слотом, вызываемым с двумя модельными индексами. Эти индексы соответствуют элементу, имевшему фокус раньше, и элементу, имеющему фокус в данный момент.

В следующем коде мы предоставляем слот, получающий сигнал currentChanged() и использующий информацию, им предоставляемую, для обновления панели состояния QMainWindow:

 void MainWindow::changeCurrent(const QModelIndex &current,
     const QModelIndex &previous)
 {
     statusBar()->showMessage(
         tr("Moved from (%1,%2) to (%3,%4)")
             .arg(previous.row()).arg(previous.column())
             .arg(current.row()).arg(current.column()));
 }

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

[править] Обновление выбора

Команды выбора специфицируются комбинацией флагов выбора, определенной как QItemSelectionModel::SelectionFlag. Каждый из флагов выбора указывает модели выбора, как изменять внутренний набор уже выбранных элементов при каждом вызове функции select(). Наиболее часто используется флаг Select, который указывает модели выбора запомнить выбранные элементы именно так, как они были выбраны. Флаг Toggle указывает модели выбора инвертировать состояние выбора всех указанных элементов, т.е. невыбранные элементы сделать выбранными, а выбранные сделать невыбранными. Флаг Deselect делает все указанные элементы невыбранными.

Отдельные элементы модели выбора обновляются с помощью создания выбора элементов и применения его к модели выбора. В следующем коде мы применяем второй выбор элементов к показанной выше табличной модели, используя команду Toggle для инвертирования состояния выбора указанных элементов.

     QItemSelection toggleSelection;
 
     topLeft = model->index(2, 1, QModelIndex());
     bottomRight = model->index(7, 3, QModelIndex());
     toggleSelection.select(topLeft, bottomRight);
 
     selectionModel->select(toggleSelection, QItemSelectionModel::Toggle);

Результат этого действия показан в табличном представлении, обеспечивающем хорошую визуализацию наших достижений:

Файл:Selected-items2.png

По умолчанию команды выбора работают только с элементами заданными модельными индексами. Однако флаг, используемый для описания команды выбора, может использоваться совместно с дополнительными флагами для изменения строк и столбцов. Например, если вы вызываете select() только с одним индексом, но с командой, которая является комбинацией флагов Select и Rows, то будет выбрана строка, содержащая элемент, на который ссылается модельный индекс. Следующий код показывает использование флагов Rows и Columns:

     QItemSelection columnSelection;
 
     topLeft = model->index(0, 1, QModelIndex());
     bottomRight = model->index(0, 2, QModelIndex());
 
     columnSelection.select(topLeft, bottomRight);
 
     selectionModel->select(columnSelection,
         QItemSelectionModel::Select | QItemSelectionModel::Columns);
 
     QItemSelection rowSelection;
 
     topLeft = model->index(0, 0, QModelIndex());
     bottomRight = model->index(1, 0, QModelIndex());
 
     rowSelection.select(topLeft, bottomRight);
 
     selectionModel->select(rowSelection,
         QItemSelectionModel::Select | QItemSelectionModel::Rows);

Несмотря на то, что модели выбора передано только четыре индекса, использование флагов выбора Columns и Rows приводит к тому, что выбираются два столбца и две строки. На следующем рисунке показан результат этого действия:

Файл:Selected-items3.png

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

Для замены текущего выбора новым, комбинируйте флаги выбора с флагом Current. Команда, использующая этот флаг, указывает, что модель выбора должна заменить свой текущий набор модельных индексов на тот, что указан при вызове select(). Для удаления прежнего выбора прежде, чем вы сделаете новый, используйте другие флаги выбора совместно с флагом Clear. Это приведет к переустановке набора модельных индексов модели выбора.

[править] Выбор всех элементов в модели

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

     QModelIndex topLeft = model->index(0, 0, parent);
     QModelIndex bottomRight = model->index(model->rowCount(parent)-1,
         model->columnCount(parent)-1, parent);

Выбор создается с этими индексами и моделью. При этом будут выбраны соответствующие элементы модели выбора:

     QItemSelection selection(topLeft, bottomRight);
     selectionModel->select(selection, QItemSelectionModel::Select);

Это должно быть сделано для всех уровней модели. Родительский индекс для элементов верхнего уровня мы определяем обычным образом:

     QModelIndex parent = QModelIndex();

В иерархических моделях для определения, является ли заданный элемент родительским для элементов более низкого уровня используется функция hasChildren().

[Предыдущая: Классы представлений ] [ Содержание ] [Следующая: Классы делегатов ]



Copyright © 2007 Trolltech Trademarks
Qt 4.3.2