问题
I'm adding checkbox items to a list view.
Then when I change the check box indicator, the item row is not selected. And when I'm selection an item in the list, the check box indicator won't change.
The checkbox indicator should be selected/deselected on item selection row, and checkbox indicator selection should set the item row selected.
List view init:
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);
Any suggestion ?
回答1:
Solved this issue by connection two signals
- Registered model item changed signal for handling the checkbox indicator change.
- Registered view item activated signal for changing the checkbox indicator state
Here's my code:
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 & )))
}
Slots implemntation :
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);
}
回答2:
You have to connect itemChanged
signal of QStandardItemModel
and select items manually there.
If you want the checkbox to be checked on selection, you'll also have to connect selectionChanged
signal of QListView::selectionModel()
and check/uncheck items there.
Also, you don't need to manually set Qt::CheckStageRole
.
Using C++11 and lambdas that would look like this:
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);
}
});
Or with old connect
syntax:
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)));
来源:https://stackoverflow.com/questions/31163516/qlistview-item-with-checkbox-selection-behavior