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 Align Center Qtableview Checkbox
Qt 6.11 is out! See what's new in the release blog

How to Align Center Qtableview Checkbox

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 4 Posters 4.1k 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.
  • D Offline
    D Offline
    DzCode
    wrote on last edited by
    #1

    Hi everyone

    In my model I am usign overriden flags() method and I am using ItemIsUserCheckable for the checkbox column of my custom tableview.

    However, everytime the checkbox is left-aligned. I cannot aligned it center or right.
    When I use margin-left and margin-right in 50% it does not work for this if the column width changes dynamically

    Is there any way to align them center without changing the my model class

    1 Reply Last reply
    1
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Searching for tableview checkbox center in the forum search gives you for example https://forum.qt.io/topic/94049/

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      D 1 Reply Last reply
      2
      • Christian EhrlicherC Christian Ehrlicher

        Searching for tableview checkbox center in the forum search gives you for example https://forum.qt.io/topic/94049/

        D Offline
        D Offline
        DzCode
        wrote on last edited by DzCode
        #3

        @Christian-Ehrlicher I looked at this topic 2 days ago. And it does not work

        JonBJ Christian EhrlicherC 3 Replies Last reply
        0
        • D DzCode

          @Christian-Ehrlicher I looked at this topic 2 days ago. And it does not work

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @DzCode
          By complete coincidence, I am about to want just this later today/tomorrow! I'll let you know how I get on, and of course keep an eye on this thread.

          1 Reply Last reply
          0
          • D DzCode

            @Christian-Ehrlicher I looked at this topic 2 days ago. And it does not work

            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @DzCode said in How to Align Center Qtableview Checkbox:

            And it does not work

            That's no problem description. Please show us your class derived from QStyledItemDelegate

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            JonBJ 1 Reply Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              @DzCode said in How to Align Center Qtableview Checkbox:

              And it does not work

              That's no problem description. Please show us your class derived from QStyledItemDelegate

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #6

              @Christian-Ehrlicher
              Hi Christian/whoever. I am now ready to try out the code(s) offered in https://forum.qt.io/topic/94049/.

              Like @DzCode, my QTableView column items have Qt::ItemIsUserCheckable, and I have the code working for Qt::CheckStateRole. I just need to move the box from the left to the center.

              But I am unsure how to proceed. I am familiar with QStyledItemDelegate, and the table already has a custom one which tests for column and does certain things on certain columns. It would be easy to add a case for the centered checkbox column, and that is what I'd like to do.

              But when I look at the code there it does stuff via class CenteredBoxProxy : public QProxyStyle. I'm afraid I am not familiar with how that works. I realize I could try it out. But you did say "Please show us your class derived from QStyledItemDelegate", and that's how I would like to do it. I do not want/need the CheckAlignmentRole and the index.data(CheckAlignmentRole) to store/fetch the alignment setting from the model.

              So... can I take the code shown there in CenteredBoxProxy::subElementRect() and put it directly into somewhere inside my QStyledItemDelegate instead? How/where?

              For example (and only as example), I see that old post from 2010 https://www.qtcentre.org/threads/29668-How-to-centering-the-checkbox-in-qtableview is doing stuff in TestDelegate::paint() --- but it is doing its own checkbox against the data, I like Qt::ItemIsUserCheckable which means Qt is handling the checkbox so I don't think that approach is right in that case?

              1 Reply Last reply
              0
              • Christian EhrlicherC Offline
                Christian EhrlicherC Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on last edited by Christian Ehrlicher
                #7

                It depends on what you want to do - if you just want to paint the checkbox in the middle without user interaction I would go for a QStyledItemDelegate similar to

                void paint(QPainter *painter,
                           const QStyleOptionViewItem &option, const QModelIndex &index) const override
                {
                
                  QStyleOptionViewItem opt = option;
                  initStyleOption(&opt, index);
                
                  QStyle *style = option.widget ? option.widget->style() : QApplication::style();
                  style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, option.widget);
                  switch (option.checkState) {
                  case Qt::Unchecked:
                      opt.state |= QStyle::State_Off;
                      break;
                  case Qt::PartiallyChecked:
                      opt.state |= QStyle::State_NoChange;
                      break;
                  case Qt::Checked:
                      opt.state |= QStyle::State_On;
                      break;
                  }
                  opt.state = opt.state & ~QStyle::State_HasFocus;
                  auto rect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, option.widget);
                  opt.rect = QStyle::alignedRect(option.direction, Qt::AlignVCenter | Qt::AlignHCenter, rect.size(), opt.rect);
                
                  painter->save();
                  painter->setClipRect(opt.rect);
                  style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, option.widget);
                  painter->restore();
                }
                

                But when you need user interaction the click you have to go with a QProxyStyle since the subElementRect is used for click detection. So @VRonin's solution is the way to go for you.

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                JonBJ 1 Reply Last reply
                0
                • Christian EhrlicherC Christian Ehrlicher

                  It depends on what you want to do - if you just want to paint the checkbox in the middle without user interaction I would go for a QStyledItemDelegate similar to

                  void paint(QPainter *painter,
                             const QStyleOptionViewItem &option, const QModelIndex &index) const override
                  {
                  
                    QStyleOptionViewItem opt = option;
                    initStyleOption(&opt, index);
                  
                    QStyle *style = option.widget ? option.widget->style() : QApplication::style();
                    style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, option.widget);
                    switch (option.checkState) {
                    case Qt::Unchecked:
                        opt.state |= QStyle::State_Off;
                        break;
                    case Qt::PartiallyChecked:
                        opt.state |= QStyle::State_NoChange;
                        break;
                    case Qt::Checked:
                        opt.state |= QStyle::State_On;
                        break;
                    }
                    opt.state = opt.state & ~QStyle::State_HasFocus;
                    auto rect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, option.widget);
                    opt.rect = QStyle::alignedRect(option.direction, Qt::AlignVCenter | Qt::AlignHCenter, rect.size(), opt.rect);
                  
                    painter->save();
                    painter->setClipRect(opt.rect);
                    style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, option.widget);
                    painter->restore();
                  }
                  

                  But when you need user interaction the click you have to go with a QProxyStyle since the subElementRect is used for click detection. So @VRonin's solution is the way to go for you.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Christian-Ehrlicher
                  Hi, thanks.

                  As I said, to be 100% percent clear. I am setting Qt::ItemIsUserCheckable because... it has to be checkable by user! I take that to mean "interactive" --- I don't only show the checkbox, I need user to be avle to click it exactly as he can right now. Only it's at the left and I want it moved to the middle....

                  So, from that I take it I must indeed follow @VRonin , and that other @Robert-Hairgrove, in that post.

                  What I do not get is the connection between: they define a class CenteredBoxProxy : public QProxyStyle class, but the only thing they do with it is app.setStyle(new CenteredBoxProxy);.

                  • I don't get how whatever knows to "execute" this style against by QTableView which happens to have Qt::ItemIsUserCheckable in some items' flags. Where is the connection?

                  • And earlier you said, when that guy claimed @VRonin code "does not work", "Please show us your class derived from QStyledItemDelegate". So now if I'm using a CenteredBoxProxy, where is any connection from that to my QStyledItemDelegate?

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Offline
                    Christian EhrlicherC Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by Christian Ehrlicher
                    #9

                    @JonB said in How to Align Center Qtableview Checkbox:

                    Where is the connection?

                    The connection is how QProxyStyle works. When you take a look at qcommonproxy.cpp you will see that every call goes through proxy() which calls the proxy style implementation (if there is one). This means that everyone who calls QStyle::drawControl(CE_ItemViewItem, ...) will call your implementation.

                    /edit: Had some time to dig into the problem: https://bugreports.qt.io/browse/QTBUG-88978

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    1 Reply Last reply
                    1
                    • D DzCode

                      @Christian-Ehrlicher I looked at this topic 2 days ago. And it does not work

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @DzCode said in How to Align Center Qtableview Checkbox:

                      @Christian-Ehrlicher I looked at this topic 2 days ago. And it does not work

                      I can now confirm that I have deployed @VRonin's code given in https://forum.qt.io/topic/94049/how-to-center-a-column-with-a-checkbox-in-qtableview/8, and it works correctly :) You did do the app.setStyle(new CenteredBoxProxy); he shows, and you did make your model's data(index, CheckAlignmentRole) so that returns Qt::AlignHCenter, didn't you?

                      [I didn't make @Robert-Hairgrove's modifications for "focus rectangle" per https://forum.qt.io/topic/94049/how-to-center-a-column-with-a-checkbox-in-qtableview/12, because TBH I couldn't see any focus rectangle anyway (Ubuntu, GNOME)!]

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        lynnepv
                        wrote on last edited by
                        #11

                        I had this issue for several years, and have read everything posted on centering a checkbox. This solution is the only one that works "perfectly". My post is for adding a focus rectangle on [TAB] keyboard focus of the centered checkbox. You'll have to read this post thoroughly for complete code, but here is the summary:

                        1. Make a derived style based on QProxyStyle. The code is below in this post. Add this code to the "elements" list:
                          if (element == SE_ItemViewItemText) {
                          retval = itemRect;
                          }
                        2. Include the headerfile at the application.h level and use setStyle( new CenteredBoxProxy ); in the application. I didn't know that a QProxyStyle gets interrogated first in the processing hierarchy for application to drawing. I spent a great deal of time trying it in ItemDelegate.
                        3. In the subclassed StyleItemDelegate createEditor function use a styleSheet on the returned editor widget.

                        QWidget* pvItemDelegate::createEditor(QWidget parent,
                        const QStyleOptionViewItem &option,
                        const QModelIndex &index) const
                        {
                        QStandardItem
                        column = index.model()->itemFromIndex(index);
                        if (column->isCheckable())
                        {
                        QWidget* w = new QWidget(parent);
                        w->setStyleSheet(QString("border-width: 1px; border-style: solid; border-color: darkblue;"));
                        return w;
                        }

                        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