Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Custom QStyledItemDelegate with a checkBox, that does not center. How to debug?
Forum Updated to NodeBB v4.3 + New Features

Custom QStyledItemDelegate with a checkBox, that does not center. How to debug?

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 1 Posters 604 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    andi456
    wrote on last edited by andi456
    #1

    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

    A 1 Reply Last reply
    0
    • A andi456

      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

      A Offline
      A Offline
      andi456
      wrote on last edited by
      #2

      @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);
         }
      }
      
      A 1 Reply Last reply
      0
      • A andi456

        @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);
           }
        }
        
        A Offline
        A Offline
        andi456
        wrote on last edited by andi456
        #3

        @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.

        A 1 Reply Last reply
        0
        • A andi456

          @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.

          A Offline
          A Offline
          andi456
          wrote on last edited by andi456
          #4

          @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 containing

          const 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.

          1 Reply Last reply
          0
          • A andi456 has marked this topic as solved on

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved