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. How to center a column with a checkbox in QTableView?
Forum Update on Monday, May 27th 2025

How to center a column with a checkbox in QTableView?

Scheduled Pinned Locked Moved Solved General and Desktop
18 Posts 7 Posters 11.2k Views
  • 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.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #8

    Try something like this:

    #include <QApplication>
    #include <QTableWidget>
    #include <QStandardItemModel>
    #include <QProxyStyle>
    #include <QStyleOptionViewItem>
    enum {
      CheckAlignmentRole = Qt::UserRole + Qt::CheckStateRole + Qt::TextAlignmentRole
    };
    class CenteredBoxProxy : public QProxyStyle{
    public:
        QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const override{
            const QRect baseRes = QProxyStyle::subElementRect(element, option, widget);
            if(element==SE_ItemViewItemCheckIndicator){
                const QStyleOptionViewItem* const itemOpt = qstyleoption_cast<const QStyleOptionViewItem*>(option) ;
                Q_ASSERT(itemOpt);
                const QVariant alignData = itemOpt->index.data(CheckAlignmentRole);
                if(alignData.isNull())
                   return baseRes;
                const QRect itemRect = option->rect;
                Q_ASSERT(itemRect.width()>baseRes.width() && itemRect.height()>baseRes.height());
                const int alignFlag = alignData.toInt();
                int x=0,y=0;
                if(alignFlag & Qt::AlignLeft){
                    x=baseRes.x();
                }
                else if(alignFlag & Qt::AlignRight){
                    x=itemRect.x() + itemRect.width() - (baseRes.x()-itemRect.x())-baseRes.width();
                }
                else if(alignFlag & Qt::AlignHCenter){
                    x=itemRect.x() + (itemRect.width()/2)-(baseRes.width()/2);
                }
                return QRect(QPoint(x,baseRes.y()), baseRes.size());
            }
            return baseRes;
        }
    };
    
    int main(int argc, char **argv)
    {
        QApplication app(argc,argv);
        app.setStyle(new CenteredBoxProxy);
        QTableView wid;
        QStandardItemModel* model = new QStandardItemModel(&wid);
        model->insertColumns(0,3);
        model->insertRows(0,10);
        for(int i=0;i<10;++i){
            model->setData(model->index(i,0), i%2==0 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
            model->setData(model->index(i,0), Qt::AlignCenter, CheckAlignmentRole);
            model->setData(model->index(i,1), i%2==0 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
            model->setData(model->index(i,2), i);
            Q_ASSERT(model->item(i,0));
            model->item(i,0)->setFlags(model->item(i,0)->flags() | Qt::ItemIsUserCheckable);
        }
        wid.setModel(model);
    
        wid.show();
        return app.exec();
    }
    

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    R 1 Reply Last reply
    5
    • VRoninV VRonin

      Try something like this:

      #include <QApplication>
      #include <QTableWidget>
      #include <QStandardItemModel>
      #include <QProxyStyle>
      #include <QStyleOptionViewItem>
      enum {
        CheckAlignmentRole = Qt::UserRole + Qt::CheckStateRole + Qt::TextAlignmentRole
      };
      class CenteredBoxProxy : public QProxyStyle{
      public:
          QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const override{
              const QRect baseRes = QProxyStyle::subElementRect(element, option, widget);
              if(element==SE_ItemViewItemCheckIndicator){
                  const QStyleOptionViewItem* const itemOpt = qstyleoption_cast<const QStyleOptionViewItem*>(option) ;
                  Q_ASSERT(itemOpt);
                  const QVariant alignData = itemOpt->index.data(CheckAlignmentRole);
                  if(alignData.isNull())
                     return baseRes;
                  const QRect itemRect = option->rect;
                  Q_ASSERT(itemRect.width()>baseRes.width() && itemRect.height()>baseRes.height());
                  const int alignFlag = alignData.toInt();
                  int x=0,y=0;
                  if(alignFlag & Qt::AlignLeft){
                      x=baseRes.x();
                  }
                  else if(alignFlag & Qt::AlignRight){
                      x=itemRect.x() + itemRect.width() - (baseRes.x()-itemRect.x())-baseRes.width();
                  }
                  else if(alignFlag & Qt::AlignHCenter){
                      x=itemRect.x() + (itemRect.width()/2)-(baseRes.width()/2);
                  }
                  return QRect(QPoint(x,baseRes.y()), baseRes.size());
              }
              return baseRes;
          }
      };
      
      int main(int argc, char **argv)
      {
          QApplication app(argc,argv);
          app.setStyle(new CenteredBoxProxy);
          QTableView wid;
          QStandardItemModel* model = new QStandardItemModel(&wid);
          model->insertColumns(0,3);
          model->insertRows(0,10);
          for(int i=0;i<10;++i){
              model->setData(model->index(i,0), i%2==0 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
              model->setData(model->index(i,0), Qt::AlignCenter, CheckAlignmentRole);
              model->setData(model->index(i,1), i%2==0 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
              model->setData(model->index(i,2), i);
              Q_ASSERT(model->item(i,0));
              model->item(i,0)->setFlags(model->item(i,0)->flags() | Qt::ItemIsUserCheckable);
          }
          wid.setModel(model);
      
          wid.show();
          return app.exec();
      }
      
      R Offline
      R Offline
      Robert Hairgrove
      wrote on last edited by
      #9

      @VRonin ... THANK YOU! This works very well.

      1 Reply Last reply
      0
      • R Offline
        R Offline
        Robert Hairgrove
        wrote on last edited by
        #10

        I saw this in qstyle.h in the "enum SubElement":

            SE_ViewItemCheckIndicator, // ### Qt 6: remove
            SE_ItemViewItemCheckIndicator = SE_ViewItemCheckIndicator,
        

        ...
        I assume that SE_ItemViewItemCheckIndicator is safe to continue to use?

        1 Reply Last reply
        1
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #11

          Hi,

          Yes it is.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • R Offline
            R Offline
            Robert Hairgrove
            wrote on last edited by
            #12

            I have adapted the code a little bit to take care of the focus rectangle which is also centered now. Of course, I will include a link to this forum topic in my code, which will be open source (thanks again, @VRonin :)

            #ifndef CENTEREDBOXPROXY_HPP
            #define CENTEREDBOXPROXY_HPP
            
            #include <QProxyStyle>
            #include <QStyleOptionViewItem>
            
            enum {
              CheckAlignmentRole = Qt::UserRole
                                 + Qt::CheckStateRole
                                 + Qt::TextAlignmentRole
            };
            
            class CenteredBoxProxy : public QProxyStyle {
            public:
              QRect subElementRect(QStyle::SubElement element,
                                   const QStyleOption *option,
                                   const QWidget *widget) const override {
                const QRect baseRes = QProxyStyle::subElementRect(element, option, widget);
                const QRect itemRect = option->rect;
                QRect retval = baseRes;
                QSize sz = baseRes.size();
            
                const QStyleOptionViewItem* const
                    itemOpt = qstyleoption_cast<const QStyleOptionViewItem*>(option);
            
                if (itemOpt) {
                  const QVariant alignData = itemOpt->index.data(CheckAlignmentRole);
                  if(!alignData.isNull()) {
                    const uint alignFlag = alignData.toUInt();
                    if (alignFlag & Qt::AlignHCenter) {
                      if (element == SE_ItemViewItemCheckIndicator) {
                        int x = itemRect.x() + (itemRect.width()/2) - (baseRes.width()/2);
                        retval = QRect( QPoint(x, baseRes.y()), sz);
                      } else if (element == SE_ItemViewItemFocusRect) {
                        sz.setWidth(baseRes.width()+baseRes.x());
                        retval = QRect( QPoint(0, baseRes.y()), sz);
                      }
                    }
                  }
                }
                return retval;
              }
            };
            
            #endif
            
            
            VRoninV 1 Reply Last reply
            2
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #13

              Thanks for the update !

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • R Robert Hairgrove

                I have adapted the code a little bit to take care of the focus rectangle which is also centered now. Of course, I will include a link to this forum topic in my code, which will be open source (thanks again, @VRonin :)

                #ifndef CENTEREDBOXPROXY_HPP
                #define CENTEREDBOXPROXY_HPP
                
                #include <QProxyStyle>
                #include <QStyleOptionViewItem>
                
                enum {
                  CheckAlignmentRole = Qt::UserRole
                                     + Qt::CheckStateRole
                                     + Qt::TextAlignmentRole
                };
                
                class CenteredBoxProxy : public QProxyStyle {
                public:
                  QRect subElementRect(QStyle::SubElement element,
                                       const QStyleOption *option,
                                       const QWidget *widget) const override {
                    const QRect baseRes = QProxyStyle::subElementRect(element, option, widget);
                    const QRect itemRect = option->rect;
                    QRect retval = baseRes;
                    QSize sz = baseRes.size();
                
                    const QStyleOptionViewItem* const
                        itemOpt = qstyleoption_cast<const QStyleOptionViewItem*>(option);
                
                    if (itemOpt) {
                      const QVariant alignData = itemOpt->index.data(CheckAlignmentRole);
                      if(!alignData.isNull()) {
                        const uint alignFlag = alignData.toUInt();
                        if (alignFlag & Qt::AlignHCenter) {
                          if (element == SE_ItemViewItemCheckIndicator) {
                            int x = itemRect.x() + (itemRect.width()/2) - (baseRes.width()/2);
                            retval = QRect( QPoint(x, baseRes.y()), sz);
                          } else if (element == SE_ItemViewItemFocusRect) {
                            sz.setWidth(baseRes.width()+baseRes.x());
                            retval = QRect( QPoint(0, baseRes.y()), sz);
                          }
                        }
                      }
                    }
                    return retval;
                  }
                };
                
                #endif
                
                
                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #14

                @Robert-Hairgrove said in How to center a column with a checkbox in QTableView?:

                retval = QRect( QPoint(0, baseRes.y()), sz);

                This seams dodgy. Could you try making the second column the one with the centred checkbox and see if it still works as expected

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                R 1 Reply Last reply
                0
                • VRoninV VRonin

                  @Robert-Hairgrove said in How to center a column with a checkbox in QTableView?:

                  retval = QRect( QPoint(0, baseRes.y()), sz);

                  This seams dodgy. Could you try making the second column the one with the centred checkbox and see if it still works as expected

                  R Offline
                  R Offline
                  Robert Hairgrove
                  wrote on last edited by Robert Hairgrove
                  #15

                  @VRonin ... Looks OK to me. But thanks for the suggestion, because I should have tried this myself before posting the update (and I hadn't).

                  The normal behavior for item views seems to be this:

                  1. When the widget has focus, the view item's focus indicator fills out the background of the entire item rectangle and is darker in color (e.g. when navigating the view with the arrow keys);
                  2. When the widget goes out of focus (e.g. clicking outside of the entire widget), there is another focus indicator which is shown, lighter in color, but only over the text normally accompanying the checkbox -- not over the checkbox itself.

                  When the checkbox has no text (i.e. when it is centered), this seems a little odd. This update "fixes" the non-focussed focus rectangle. :)

                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #16

                    Sorry I should have been more specific, my only concern is on having 0 as first argument to QPoint there as I think it's in coordinates of the scrollarea not of the item itself so my concern is that if the checkbox is in any column except the first column, retval would still point somewhere in the first column

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    0
                    • A.A.SEZENA A.A.SEZEN

                      You can try a different use...
                      Add QWidget instead of QCheckBox in your QTableView.
                      for example:

                       QWidget * checkWidget = new QWidget(this);
                       QCheckBox * check = new QCheckBox(this);
                       QHBoxLayout * checkLayout = new QHBoxLayout(checkWidget);
                        checkLayout->addWidget(check);
                        checkLayout->setAlignment(Qt::AlignCenter);
                        checkLayout->setContentsMargins(0,0,0,0);
                      

                      // add checkWidget to QTableView

                      A Offline
                      A Offline
                      Alexey Serebryakov
                      wrote on last edited by
                      #17

                      @A-A-SEZEN It does not work.

                      A.A.SEZENA 1 Reply Last reply
                      0
                      • A Alexey Serebryakov

                        @A-A-SEZEN It does not work.

                        A.A.SEZENA Offline
                        A.A.SEZENA Offline
                        A.A.SEZEN
                        wrote on last edited by
                        #18

                        @Alexey-Serebryakov .. I am actively using those codes. With only one difference. QTableWidget instead of QTableView.

                                            else if(yapi->slAlan[i] == "ISLEM") {
                                                auto * checkWidget = new QWidget(this);
                                                auto * check = new QCheckBox(this);
                                                auto * checkLayout = new QHBoxLayout(checkWidget);
                                                checkLayout->addWidget(check);
                                                checkLayout->setAlignment(Qt::AlignCenter);
                                                checkLayout->setContentsMargins(0,0,0,0);
                                                check->setMaximumWidth(yapi->slColumnWidth[i].toInt());
                                                check->setChecked(q.value(yapi->slAlan[i]).toString() == "2");
                                                check->setCheckable(!bPasif);
                                                if(!renk.isEmpty()) {
                                                    checkWidget->setStyleSheet(tr("background-color: %1").arg(renk));
                                                }
                                                tablo->setCellWidget(iSatir, i, checkWidget);
                                                checkWidget->setContextMenuPolicy(Qt::CustomContextMenu);
                                                connect(checkWidget, &QMenu::customContextMenuRequested, this, &kucukbas::doganPopupMenu);
                                                connect(check, &QCheckBox::stateChanged, this, [=]() {
                                                    doganKaydet("ISLEM",
                                                                check->isChecked() ? "2" : "0",
                                                                idDogan());
                                                });
                                            }
                        
                        
                        1 Reply Last reply
                        0

                        • Login

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