Custom QItemDelegate works in QTableView but not QTreeView
-
I wrote a custom
QItemDelegate
to put aQCheckBox
in a column of aQTableView
which worked quite well:#include <QCheckBox> #include <QHBoxLayout> #include "toolwidget/checkboxdelegate.h" CheckboxDelegate::CheckboxDelegate(QObject* parent) : QItemDelegate(parent) { } QWidget* CheckboxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(option) Q_UNUSED(index) // Create a new checkbox. Use a layout to align (center) it. QCheckBox* editor = new QCheckBox(parent); editor->setObjectName("CheckBox"); QHBoxLayout* layout = new QHBoxLayout; layout->addStretch(); layout->addWidget(editor); layout->addStretch(); QWidget* editorWidget = new QWidget(parent); editorWidget->setLayout(layout); return editorWidget; } void CheckboxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { // Retrieve the checked state from the item bool checked = index.model()->data(index, Qt::EditRole).toBool(); // Retrieve the checkbox QCheckBox* checkbox = static_cast<QCheckBox*>(editor->findChild<QCheckBox*>("CheckBox")); if (!checkbox) { qCritical("CheckboxDelegate::setEditorData(): Couldn't retrieve QCheckBox. Aborting."); return; } // Set the checkbox state checkbox->setChecked(checked); } void CheckboxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { QCheckBox* checkbox = static_cast<QCheckBox*>(editor->findChild<QCheckBox*>("CheckBox")); if (!checkbox) { qCritical("CheckboxDelegate::setModelData(): Couldn't retrieve QCheckBox. Aborting."); return; } // Set the model data model->setData(index, checkbox->isChecked(), Qt::EditRole); } void CheckboxDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(index) editor->setGeometry(option.rect); } void CheckboxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // Retrieve the checked state from the item Qt::CheckState checkState = index.model()->data(index, Qt::DisplayRole).toBool() ? Qt::Checked : Qt::Unchecked; // Render drawCheck(painter, option, option.rect, checkState); } QSize CheckboxDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(option) Q_UNUSED(index) QCheckBox checkbox; return checkbox.sizeHint(); }
Now I decided that I'd much rather use a
QTreeView
than aQTableView
because I want to introduce hierarchies in my model. The problem is that myCheckboxDelegate
doesn't work there anymore.
I still see the checkbox being rendered but I can't change the state of it anymore. When I click on it I see thatQAbstractItemModel::setData()
is being called successfully but it always writes back the same value - this means that the checkbox never gets toggled.I'm a bit lost here. I don't know how much more information is required. Any ideas?
-
Hi,
Out of curiosity, why not return item flag Qt::ItemIsUserCheckable from your model ? IIRC it should provide you with what you need directly and avoid the need of a custom delegate.
On a side note, you should use qobject_cast when dealing with QObject casting. static_cast doesn't do any validation.
-
I tried using
Qt::ItemIsUserCheckable
and it has the expected effect. However, instead of displaying a regular checkbox it displayed a combobox with the values "True" and "False". Hence the custom delegate.I replaced the
static_cast
withqobject_cast
as per your recommendation. Of course, as expected, this didn't affect the problem that I'm having.Any ideas?
-
I also modified my model. Actually, when I was still using the
QTableView
I followed exactly the example you linked and I got it working. The reason why I created my own custom delegate anyway is because I want one single checkbox that is centered in the cell. The "built-in" feature (as shown in the example you linked) adds a checkbox to the decoration of a cell.As mentioned everything works well in a
QTableView
. It's just that it doesn't work that well in aQTreeView
. -
Can you setup a minimal project that shows the behavior ?
-
At the end, @SGaist pointed me to this implementation of a checkbox item delegate which works very well.