[Qt] QListView – как реализовать множественный выбор.

Компонент, о котором пойдет в этой статье, используется часто в самых различных ситуациях. И это в принципе не удивительно, QListView во первых позволяет удобно отображать самые разные типы данных, во вторых – в полной мере реализует принцип Model-View (модель-представление).
Но начинающих часто может поставить в тупик – как реализовать множественный выбор в данном компоненте (да и не только в нем – данный подход достаточно универсален для всех компонентов, которые наследуют от QAbstractItemView)?
Сейчас я попытаюсь показать – как это можно сделать.
Для начала предположим, что у нас на форме находится компонент типа QListView, назовем его lwMain. Данный компонент отображает данные из модели QSqlQueryModel, которая получает из базы два поля – идентификатор и имя объекта. Наша задача – получить список выбранных идентификаторов и имен – и передать их далее.
Для реализации множественного выбора необходимо установить поле selectionMode в значение QAbstractItemView::MultiSelection либо QAbstractItemView::ExtendedSelection. Эти два типа отличаются тем, что в последнем случае множественный выбор происходит только при зажатой клавише Shift либо Ctrl

Установить значение поля можно в дизайнере форм, либо используя следующий код:

ui->lwMain->setSelectionMode(QAbstractItemView::MultiSelection);

Так же, имеет значение состояние поля selectionBehavior – возможны варианты: QAbstractItemView::SelectItems, QAbstractItemView::SelectRows, QAbstractItemView::SelectColumns. Разница между этими тремя типами понятна из названия – в первом случае выбирается только одно поле, во втором – соответственно строка целиком, в третьем – столбец. Все зависит от того, что вы хотите получить, и как планируете организовывать работу со своими данными. Если вы используете QAbstractItemView::SelectItems – для того что бы получить идентификатор и имя вашей записи – необходимо использовать два списка – один для идентификаторов, второй для имен. Если же вы установили QAbstractItemView::SelectRows – то полученные значения будут добавляться в один массив двумя строками – первым будет добавлен идентификатор, второй строкой – имя. Установка свойства selectionBehavior может быть выполнена либо в дизайнере форм, либо программным кодом:

ui->lwMain->setSelectionBehavior(QAbstractItemView::SelectItems);

Для того, что бы получить список выбранных строк в компоненте необходимо обратиться к методу selectionModel(), возвращающий указатель на модель данных для выбранных строк QItemSelectionModel*, которая, в свою очередь, имеет метод selectedIndexes(). Как понятно из названия, этот метод возвращает QModelIndexList – список индексов, который можно использовать для доступа к выделенным данным.
Дальнейшие наши действия зависят от того, какой тип выделения записей(тот самый selectionBehavior) вы решили использовать.
Если это QAbstractItemView::SelectItems вам необходимо будет создать необходимое количество списков по числу полей, которые вы хотите использовать. Например, в приведенном примере мне нужно создать два списка – в одном будет содержаться идентификатор, во втором – наименование. Выглядит это следующим образом:

QStringList list; //Список для имен
QListindex; //Список для идентификаторов
QModelIndexList mlist = ui->lwMain->selectionModel()->selectedIndexes();
QSqlQueryModel *mod = (QSqlQueryModel*)ui->lwMain->model();//Получаем указатель на модель данных
for(int i = 0;i < mlist.count();i++){
//Получаем отображаемое имя
list.append(mlist.at(i).data(Qt::DisplayRole).toString());
//Обращаемся к записи в модели данных и получаем из нее идентификатор
index.append(mod->record(mlist.row()).value("id").toInt());
}
//используем полученное, например:
...
for(int i = 0; i < list.count();i++){
html += list.at(i) + ";";
}
...
//Или так
...
foreach(QString name,list){
html += name + ";";
}
...

В результате выполнения этого кода в списке list будут находится имена выбранных строк, а в списке index – их идентификаторы типа int.


list:
“Приходные документы”,
“Документы списания”


index:
2,
5

Как видно, число добавленных элементов в обоих массивах будет равно числу выделенных строк.
Если вы используете QAbstractItemView::SelectRows – то ваш код будет выглядеть по другому. Во первых, нет необходимости в нескольких массивах – все будет храниться в одном. Во вторых – сам код гораздо проще:

QStringList list; //Один список
QModelIndexList mlist = ui->lwMain->selectionModel()->selectedIndexes();
for(int i = 0;i < mlist.count();i++){
list.append(mlist.at(i).data(Qt::DisplayRole).toString());
}
//используем полученное
...

Наш list в этом случае будет содержать:

list:
2,
“Приходные документы”,
5,
“Документы списания”

Что в этом случае проще – зависит от ваших задач.
Надеюсь данный материал будет вам полезен. Если есть какие либо вопросы и пожелания пишите.

©Varkon Ltd 2010
При перепечатке материала ссылка на данный сайт обязательна.
ООО Варкон. Высококачественный сервис и поддержка.

Если статья была полезна вам – не забывайте поделиться ею со своими друзьями в социальных сетях. Если есть вопросы – задавайте в комментариях либо в наших социальных группах.