Custom QStyledItemDelegate with a checkBox, that does not center. How to debug?
-
Hi,
first of all, my modest aim is to write a custom QStyledItemDelegate with a CheckBox as editor for a TableView that colorizes the background under certain conditions.
Colorizing works, but using the checkBox does not. Whenever I click on a cell with the corresponding checkBox, another checkBox is being displayed to the left. What could be the cause of this? Where else should I place code to center the checkBox, that is being edited?
Thanks in advance,
Kind regards,
Andreas
-
Hi,
first of all, my modest aim is to write a custom QStyledItemDelegate with a CheckBox as editor for a TableView that colorizes the background under certain conditions.
Colorizing works, but using the checkBox does not. Whenever I click on a cell with the corresponding checkBox, another checkBox is being displayed to the left. What could be the cause of this? Where else should I place code to center the checkBox, that is being edited?
Thanks in advance,
Kind regards,
Andreas
@andi456 Here is my paint function, which I suspect to be the cause of the problem:
void CheckBoxZDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; int grad_spalte = this->get_idxFromHeader("Grad"); int grad = this->get_intFromVariant(index.siblingAtColumn(grad_spalte).data(Qt::DisplayRole)); if (grad==0) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==1) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==2) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==3) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==4) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==5) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==6) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==7) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==8) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==9) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } initStyleOption(&opt, index); auto * widget = opt.widget; auto * style = widget->style(); int zeile = index.row(); QVariant value = index.data(Qt::CheckStateRole); // if (!value.isValid()) int cb_value = get_intFromVariant(value); //qDebug() << "Paint Method, index data " << cb_value; if ((style) && (zeile < index.model()->rowCount() - 1)) { /*QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &opt); int chkWidth=checkBoxRect.width(); int chkHeight=checkBoxRect.height(); int centerX=opt.rect.left() + qMax(opt.rect.width()/2-chkWidth/2, 0); int centerY=opt.rect.top() + qMax(opt.rect.height()/2-chkHeight/2, 0); opt.rect.moveTo(centerX, centerY); opt.rect.setSize(QSize(chkWidth, chkHeight)); */ opt.state.setFlag(QStyle::State_HasFocus, false); opt.features.setFlag(QStyleOptionViewItem::HasDisplay, true); opt.features.setFlag(QStyleOptionViewItem::HasDecoration, false); opt.features.setFlag(QStyleOptionViewItem::HasCheckIndicator, true); if (cb_value== Qt::Checked) { auto stateFlag = QStyle::State_On; opt.state.setFlag(stateFlag, true); //qDebug() << "STateFlag auf ON"; } else { auto stateFlag = QStyle::State_Off; opt.state.setFlag(stateFlag, true); // qDebug() << "STateFlag auf Off"; } opt.rect = this->getCheckBoxRect(opt); style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget); //qDebug() << "Checkbox delegate paint method called"; style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, widget); } else { painter->setPen(Qt::black); //int spalte = index.column(); opt.features.setFlag(QStyleOptionViewItem::HasCheckIndicator, false); //QVariant value = QString cell_text = index.model()->data(index, Qt::CheckStateRole).toString(); qDebug() << "Painter Method: " << cell_text; //if (value.canConvert<QString>() && value.convert(QVariant::String)) { painter->drawText(opt.rect, Qt::AlignCenter, cell_text); //} //QString cell_text = QString::number(sum_Flags); // painter->drawText(opt.rect, Qt::AlignCenter, cell_text); } } -
@andi456 Here is my paint function, which I suspect to be the cause of the problem:
void CheckBoxZDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; int grad_spalte = this->get_idxFromHeader("Grad"); int grad = this->get_intFromVariant(index.siblingAtColumn(grad_spalte).data(Qt::DisplayRole)); if (grad==0) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==1) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==2) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==3) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==4) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==5) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==6) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==7) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==8) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } else if (grad==9) { this->paint_pro_grad(grad, cbud_grad_color_qvec, painter, opt.rect); } initStyleOption(&opt, index); auto * widget = opt.widget; auto * style = widget->style(); int zeile = index.row(); QVariant value = index.data(Qt::CheckStateRole); // if (!value.isValid()) int cb_value = get_intFromVariant(value); //qDebug() << "Paint Method, index data " << cb_value; if ((style) && (zeile < index.model()->rowCount() - 1)) { /*QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &opt); int chkWidth=checkBoxRect.width(); int chkHeight=checkBoxRect.height(); int centerX=opt.rect.left() + qMax(opt.rect.width()/2-chkWidth/2, 0); int centerY=opt.rect.top() + qMax(opt.rect.height()/2-chkHeight/2, 0); opt.rect.moveTo(centerX, centerY); opt.rect.setSize(QSize(chkWidth, chkHeight)); */ opt.state.setFlag(QStyle::State_HasFocus, false); opt.features.setFlag(QStyleOptionViewItem::HasDisplay, true); opt.features.setFlag(QStyleOptionViewItem::HasDecoration, false); opt.features.setFlag(QStyleOptionViewItem::HasCheckIndicator, true); if (cb_value== Qt::Checked) { auto stateFlag = QStyle::State_On; opt.state.setFlag(stateFlag, true); //qDebug() << "STateFlag auf ON"; } else { auto stateFlag = QStyle::State_Off; opt.state.setFlag(stateFlag, true); // qDebug() << "STateFlag auf Off"; } opt.rect = this->getCheckBoxRect(opt); style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget); //qDebug() << "Checkbox delegate paint method called"; style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, widget); } else { painter->setPen(Qt::black); //int spalte = index.column(); opt.features.setFlag(QStyleOptionViewItem::HasCheckIndicator, false); //QVariant value = QString cell_text = index.model()->data(index, Qt::CheckStateRole).toString(); qDebug() << "Painter Method: " << cell_text; //if (value.canConvert<QString>() && value.convert(QVariant::String)) { painter->drawText(opt.rect, Qt::AlignCenter, cell_text); //} //QString cell_text = QString::number(sum_Flags); // painter->drawText(opt.rect, Qt::AlignCenter, cell_text); } }@andi456 I see, setEditorData fetches the value from the corresponding model. What I am concerned about is the setModelData function....
Further investigation leads me to assume that i have to reimplement the editorEvent method as well. This post seems to indicate this.
It is a little counterintuitive that the activated editor is being drawn in a different position than the deactivated one.
-
@andi456 I see, setEditorData fetches the value from the corresponding model. What I am concerned about is the setModelData function....
Further investigation leads me to assume that i have to reimplement the editorEvent method as well. This post seems to indicate this.
It is a little counterintuitive that the activated editor is being drawn in a different position than the deactivated one.
@andi456 Just in case someone has a similar problem. The solution for me was indeed the hint given in the link above.
As can be seen from the posted paint method above, I use a function to determine the rectangle of the checkBox, which looks like this
QRect CheckBoxZBuchDeckDelegate::getCheckBoxRect(const QStyleOptionViewItem &option) const { QStyleOptionViewItem opt = option; auto widget = opt.widget; auto style = widget->style(); auto checkboxSize = style->subElementRect(QStyle::SE_CheckBoxIndicator, &option, widget).size(); return QStyle::alignedRect(option.direction, Qt::AlignCenter, checkboxSize, option.rect); }So I just used the same function in the eventEditor method copied from the qt-sources of qstyleditemdelegate.cpp
after deleting the lines containingconst QWidget *widget = QStyledItemDelegatePrivate::widget(option); QStyle *style = widget ? widget->style() : QApplication::style();I replaced
QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget);with
QRect checkRect = this->getCheckBoxRect(option);et voilĂ .
If a QStyledItemDelegate should answer to an event, the area to be clicked has to be announced to the editorEvent too.
-
A andi456 has marked this topic as solved on