Custom QItemDelegate works in QTableView but not QTreeView
-
wrote on 21 Jun 2016, 17:53 last edited by Joel Bodenmann
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.
-
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.
wrote on 21 Jun 2016, 22:18 last edited byI 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?
-
You also need to modify your data function for the corresponding role.
See the "extending the read only example with roles" part of the model view tutorial here.
-
You also need to modify your data function for the corresponding role.
See the "extending the read only example with roles" part of the model view tutorial here.
wrote on 21 Jun 2016, 22:44 last edited byI 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 ?
-
wrote on 23 Jun 2016, 21:35 last edited by Joel Bodenmann
Yup, here you go: <link_removed>
I hope that helps... really lost here.I am using Qt 5.6.1 on Windows 10 64-Bit with MinGW 4.9.2.
-
Yup, here you go: <link_removed>
I hope that helps... really lost here.I am using Qt 5.6.1 on Windows 10 64-Bit with MinGW 4.9.2.
wrote on 30 Jun 2016, 07:05 last edited by Joel BodenmannAt the end, @SGaist pointed me to this implementation of a checkbox item delegate which works very well.
5/8