QListView具有复选框选择行为的项目

QListView item with checkbox selection behavior

本文关键字:项目 选择 复选框 QListView      更新时间:2023-10-16

我正在将复选框项添加到列表视图中。

然后,当我更改复选框指示器时,项目行不会被选中。当我在列表中选择一个项目时,复选框指示器不会改变。

应在项目选择行上选择/取消选择复选框指示符,复选框指示符的选择应设置所选项目行。

列表视图初始化:

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);

有什么建议吗?

通过连接两个信号解决了这个问题

  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);
}

您必须连接QStandardItemModelitemChanged信号,并在那里手动选择项目。

如果你想在选择时选中复选框,你还必须连接QListView::selectionModel()selectionChanged信号,并在那里选中/取消选中项目。

此外,您不需要手动设置Qt::CheckStageRole

使用C++11和lambdas,如下所示:

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)));