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

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

Обработка Выбора в Представлениях Элементов

Концепции

В модели выбора, предлагаемоей в новых классах представлений элементов, предоставляется множество усовершенствований по сравнению с моделью выбора 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);

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

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

Чтение Состояния Модели Выбора

Модельные индексы, хранящиеся в модели выбора, могут быть прочитаны с помощью функции 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);

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

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

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

Для замены текущего выбора новым, комбинируйте флаги выбора с флагом 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 © 2005 Trolltech Trademarks
Qt 4.1.0
Hosted by uCoz