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 dynamicallyIs there any way to align them center without changing the my model class
-
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 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 haveQt::ItemIsUserCheckable
, and I have the code working forQt::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 fromQStyledItemDelegate
", and that's how I would like to do it. I do not want/need theCheckAlignmentRole
and theindex.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 myQStyledItemDelegate
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 likeQt::ItemIsUserCheckable
which means Qt is handling the checkbox so I don't think that approach is right in that case? -
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 isapp.setStyle(new CenteredBoxProxy);
.-
I don't get how whatever knows to "execute" this style against by
QTableView
which happens to haveQt::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 myQStyledItemDelegate
?
-
-
@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'sdata(index, CheckAlignmentRole)
so that returnsQt::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)!]
-
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:
- 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;
} - 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.
- 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;
} - Make a derived style based on QProxyStyle. The code is below in this post. Add this code to the "elements" list: