Transparency in Table/Tree View/WIdget with setAlternatingRowColors and Delegate
-
Hello,
I have a problem when I set alternate row-color to table/tree view/widgets (tested on QTreeView as well as QTableWidget).
The problem is, that for each second row the background of the delegate is not painted and will be transparent.
Therefore when the columns are too small to fit the content it will not get hidden but overlap with the neighboring cell.
This will not be the case for the alternating row where it renders as expected.A minimal example can be easily generated by using the StarDelgate example from the Qt-Examples and adding
tableWidget.setAlternatingRowColors(true); in main.
If it helps I can upload it as well.
-
Hi
Its just a bug in that sample.You can fix it by clipping to the cell rect.
void StarRating::paint(QPainter *painter, const QRect &rect, const QPalette &palette, EditMode mode) const { painter->save(); painter->setClipRect(rect); <<<<<<<<<<<<<<<<<<<<<<<<<<<< NEW we clip it. painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); painter->setBrush(mode == EditMode::Editable ? palette.highlight() : palette.windowText()); const int yOffset = (rect.height() - PaintingScaleFactor) / 2; painter->translate(rect.x(), rect.y() + yOffset); painter->scale(PaintingScaleFactor, PaintingScaleFactor); for (int i = 0; i < myMaxStarCount; ++i) { if (i < myStarCount) painter->drawPolygon(starPolygon, Qt::WindingFill); else if (mode == EditMode::Editable) painter->drawPolygon(diamondPolygon, Qt::WindingFill); painter->translate(1.0, 0.0); } painter->restore(); }
-
@mrjj Thanks for the hint.
I've tried your approach with clipping.
This works, however it leads to strange behavior at the border making some parts of the editor overlap the scrollbar on the side of the view sometimes.I guess setClipRect() overwrites the default clipping in that area?
-
@gde23
Hi
I dont think its due to clipping as setClipRect()
cannot make it possible to draw outside the client rect into other widgets as far as i know, so
so i think its something else. :)Can you tell me how to reproduce the effect or can you show a picture?
-
@mrjj
I currently cannot reproduce it with the stardelegate example, only with my larger project where it is hard to isolate a minimal example.Here is a screenshot that shows what I mean:
My delegates have something like a row-header for each row (the grey bar) and it overlaps to the right out of the view into the neighboring widget (blue/grey) and over the scrollbar. This is not only the case for the row-header but any part of the delegate sometimes overlaps, its kind of random.
However the problem only occurs as soon as I add setCliptRect(), without that line it works as expected.
My painter function looks something like this:
//... set editor data and so on QStyleOptionViewItem option_widget = option; QStyledItemDelegate::initStyleOption(&option_widget, index); painter->save(); painter->setClipRect(option.rect); editor->setPalette(option_widget.palette); editor->resize(option_widget.rect.size()); painter->translate(option_widget.rect.topLeft()); editor->render(painter, QPoint(), QRegion(), QWidget::DrawChildren); painter->restore();
-
@gde23
Hi
I think it's your editor as only a widget can overlap the scrollbar this way.
You should not be able to paint outside the viewport() as far as i know and even if you could we
limit painter to the cell rect.have you checked the values from
editor->resize(option_widget.rect.size());
and see if that could extend out over the scrollbar. -
The whole editor is not resizing over the border (as you also can see in the picture only the editor-header-widget overlays the outer area.
I've found out something more: The problem only occurs when a stylesheet is set.
It is enough to have following general entry in there:QWidget { color: #000000; background: #f0f0f0; border: 2px solid transparent; font-size: 9pt; }
when I change it to
QWidget { color: #000000; }
the problem is gone,
however withQWidget { color: #000000; background: #f0f0f0; }
its still there .
This does not make a lot of sense to me. -
@mrjj
My editer is a Qwigdet with a layout on it and inside the layout there are other widgets.
I have not reimplemented any painting for it, so it just uses the default paint routines.The paint from the delegate is this:
void TreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const { QWidget* editor = nullptr; editor = new DummyDelegate(); QStyleOptionViewItem option_widget = option; QStyledItemDelegate::initStyleOption(&option_widget, index); painter->save(); painter->setClipRect(option.rect); editor->setPalette(option_widget.palette); editor->resize(option_widget.rect.size()); painter->translate(option_widget.rect.topLeft()); editor->render(painter, QPoint(), QRegion(), QWidget::DrawChildren); painter->restore(); delete editor; }
What also maybe could cause the problem is, that the TreeView I'm am using has a frozen column, like in the FrozenTableView example. Really hard to isolate the source of the problem. I guess I'll have to try to recreate it on a minimal example.
EDIT: nope, that wasn't involved. Still there without frozen columns -
Hi
I think its the editor as that would also explain
QWidget {
color: #000000;
background: #f0f0f0;
}so to test that please
do
editor->resize(option_widget.rect.size());
editor->resize(QRect(0,0,50,50);and if that grey thing then is small, then you know why.
-
Thanks for the further hint. I've tried that, the grey header is smaller now, but it still may overlap.
What I've also noticed is, that the Text seems to be renderd twice with a small ofset somehow when it is overlapping.
Also with the text when i do not clip to rect the overlap is gone.
-
@mrjj
Ok :) so but what could be the reason? Or do you have any ideas for fixing it?EDIT: I've also tested some "compact mode" where i can remove the header from the cells, and the view will be shown without the cell headers.
When I switch to compact mode the artefacts stay there for a while and only dissapear after a few clicks or something.
So at that moment the editors arent even there any more. Could this be a timing problem maybe? -
Dummy Delegate is just a normal widget with layouts on it that hold other widgets
DummyDelegat::DummyDelegat(QWidget *parent): QWidget(parent), m_compact_mode(false) { m_main_layout = new QVBoxLayout(); m_main_layout->setSpacing(2); m_main_layout->setContentsMargins(0, 0, 0, 0); m_main_layout->setAlignment(Qt::AlignTop); this->setLayout(m_main_layout); m_header = new QWidget(this); m_header->setFixedHeight(12); m_main_layout->addWidget(m_header); m_header_layout = new QHBoxLayout(); m_header_layout->setContentsMargins(5, 0, 0, 0); m_header_layout->setSpacing(2); m_header->setLayout(m_header_layout); m_header_icon_label = new QLabel(this); m_header_icon_label->setFixedHeight(12); m_header_icon_label->setFixedWidth(12); m_header_layout->addWidget(m_header_icon_label); m_header_label = new QLabel(this); m_header_layout->addWidget(m_header_label); }
-
@gde23
Ok. I have no idea then
as its clearly the grey we see.I wonder one thing
You don't give it a parent when you new it -
so how do you avoid it having borders etc like a Window normally have?editor = new DummyDelegate( NO PARENT );
Also you could try to give it a parent to see if that keeps it inside