I'd like to draw 'clickable' icons (or buttons) on each row of a QListView I'm using my own custom "QAbstractItemDelegate" derived class to paint. Those buttons may change with the custom status of the row (i have access to the underlying data structure during painting).
What's the best way to approach this?
DISCLAIMER: This may not be the best way, but here is a way where you have full control. We found it necessary to do this with drawing check boxes.
You can inherit from QStyledItemDelegate
(or QAbstractItemDelegate
may work .. have not tried it) and reimplement the paint
and editorEvent
methods. You use QStyle::drawControl()
(after setting the appropriate style options) to draw the control in paint
, and then manually test for a mouse hit in the editorEvent
and do something with it. If memory serves me correctly, this code was largely inspired (cough, copied, cough, cough) from looking at the Qt source code for the QStyledItemDelegate
.
void CheckBoxDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const {
bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
if (option.state & QStyle::State_Selected) {
painter->setPen(QPen(Qt::NoPen));
if (option.state & QStyle::State_Active) {
painter->setBrush(QBrush(QPalette().highlight()));
}
else {
painter->setBrush(QBrush(QPalette().color(QPalette::Inactive,
QPalette::Highlight)));
}
painter->drawRect(option.rect);
}
QStyleOptionButton check_box_style_option;
check_box_style_option.state |= QStyle::State_Enabled;
if (checked) {
check_box_style_option.state |= QStyle::State_On;
} else {
check_box_style_option.state |= QStyle::State_Off;
}
check_box_style_option.rect = CheckBoxRect(option);
QApplication::style()->drawControl(QStyle::CE_CheckBox,
&check_box_style_option,
painter);
}
bool CheckBoxDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index) {
if ((event->type() == QEvent::MouseButtonRelease) ||
(event->type() == QEvent::MouseButtonDblClick)) {
QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
if (mouse_event->button() != Qt::LeftButton ||
!CheckBoxRect(option).contains(mouse_event->pos())) {
return true;
}
if (event->type() == QEvent::MouseButtonDblClick) {
return true;
}
} else if (event->type() == QEvent::KeyPress) {
if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space &&
static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select) {
return false;
}
} else {
return false;
}
bool checked = model->data(index, Qt::DisplayRole).toBool();
return model->setData(index, !checked, Qt::EditRole);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With