Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to Align Center Qtableview Checkbox



  • 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


  • Lifetime Qt Champion

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



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



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


  • Lifetime Qt Champion

    @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



  • @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?


  • Lifetime Qt Champion

    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.



  • @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?


  • Lifetime Qt Champion

    @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



  • @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)!]


Log in to reply