Элемент QListView с поведением выбора флажка

Я добавляю элементы-флажки в список.

Затем, когда я меняю индикатор флажка, строка элемента не выделяется. И когда я выбираю элемент в списке, индикатор флажка не изменится.

Индикатор флажка должен быть выбран / снят с выбора в строке выбора элемента, а выбор индикатора флажка должен установить выбранную строку элемента.

Начало просмотра списка:

QListView *poListView = new QListView(this);

// Create list view item model
QStandardItemModel*  poModel =
          new QStandardItemModel(poListView);

QStandardItem *poListItem = new QStandardItem;

// Checkable item
poListItem->setCheckable( true );

// Uncheck the item
poListItem->setCheckState(Qt::Unchecked);

// Save checke state
poListItem->setData(Qt::Unchecked, Qt::CheckStateRole);

poModel->setItem(0, poListItem);

poListView->setModel(poModel);

Любое предложение?

2 ответа

Решил эту проблему путем соединения двух сигналов

  1. Зарегистрированный элемент модели изменил сигнал для обработки изменения индикатора флажка.
  2. Активированный сигнал зарегистрированного элемента просмотра для изменения состояния индикатора флажка

Вот мой код:

void MyClass:Init() 
{
    m_poListView = new QListView(this);

    // Set single selection mode
    m_poListView->setSelectionMode(
               QAbstractItemView::SingleSelection);

    // Create list view item model
    QStandardItemModel*  poModel =
              new QStandardItemModel(m_poListView);

    QStandardItem * poListItem =
              new QStandardItem;

    // Checkable item
    poListItem->setCheckable( true );

    // Save checke state
    poListItem->setData(Qt::Unchecked, Qt::CheckStateRole);

    poModel->setItem(0, poListItem);

    m_poListView->setModel(poModel);

     // Register model item  changed signal
       connect(poModel, SIGNAL(itemChanged(QStandardItem*)),
       this,            SLOT  (SlotItemChanged(QStandardItem*)));

    // Resister view item acticated
     connect( m_poListView , SIGNAL(activated(const QModelIndex & )),
                 this,       SLOT(SlotListItemActivated(const QModelIndex & )))

}

Реализация слотов:

void MyClass::SlotItemChanged(QStandardItem *poItem)
{
    // Get current index from item
    const QModelIndex oCurrentIndex =
            poItemChanged->model()->indexFromItem(poItem);

    // Get list selection model
    QItemSelectionModel *poSelModel =
            m_poListView->selectionModel();

    // Set selection
    poSelModel->select(
                QItemSelection(oCurrentIndex, oCurrentIndex),
                QItemSelectionModel::Select | QItemSelectionModel::Current);
}

void MyClass::SlotListItemActivated(const QModelIndex &oIndex)
{
    Qt::CheckState eCheckState = Qt::Unchecked;

    // Get item's check state
    bool bChecked =
            oIndex.data(Qt::CheckStateRole).toBool();

    // Item checked ?
    if (bChecked == false) 
        eCheckState = Qt::Checked;
    else 
        eCheckState = Qt::Unchecked;

    // Get index model
      //    Note: I used QSortFilterProxyModel in the original code
    QSortFilterProxyModel *poModel = 
        (QSortFilterProxyModel *)oIndex.model();

    // Update model data
    poModel->setData(oIndex, eCheckState, Qt::CheckStateRole);
}

Вы должны подключиться itemChanged сигнал о QStandardItemModel и выберите элементы вручную там.

Если вы хотите, чтобы флажок был отмечен при выборе, вам также необходимо подключиться selectionChanged сигнал о QListView::selectionModel() и отметьте / снимите галочки там.

Кроме того, вам не нужно вручную устанавливать Qt::CheckStageRole,

Используя C++11 и лямбды, которые будут выглядеть так:

connect(poModel, &QStandardItemModel::itemChanged, [poListView, poModel](QStandardItem * item) {
    const QModelIndex index = poModel->indexFromItem(item);
    QItemSelectionModel *selModel = poListView->selectionModel();
    selModel->select(QItemSelection(index, index), item->checkState() == Qt::Checked ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
});

connect(poListView->selectionModel(), &QItemSelectionModel::selectionChanged, [poModel](const QItemSelection &selected, const QItemSelection &deselected) {
    for (const QModelIndex &index : selected.indexes()) {
        poModel->itemFromIndex(index)->setCheckState(Qt::Checked);
    }
    for (const QModelIndex &index : deselected.indexes()) {
        poModel->itemFromIndex(index)->setCheckState(Qt::Unchecked);
    }
});

Или со старым connect синтаксис:

void MyClass::handleCheckedChanged(QStandardItem *item) {
    const QModelIndex index = item->model()->indexFromItem(item);
    QItemSelectionModel *selModel = poListView->selectionModel();
    selModel->select(QItemSelection(index, index), item->checkState() == Qt::Checked ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
}

void MyClass::handleSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {
    foreach (const QModelIndex &index, selected.indexes()) {
        index.model()->itemFromIndex(index)->setCheckState(Qt::Checked);
    }
    foreach (const QModelIndex &index, deselected.indexes()) {
        index.model()->itemFromIndex(index)->setCheckState(Qt::Unchecked);
    }
}

...

connect(poModel, SIGNAL(itemChanged(QStandardItem *)), this, SLOT(handleCheckedChanged(QStandardItem *)));

connect(poListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged(QItemSelection, QItemSelection)));
Другие вопросы по тегам