When setting the background of a QScrollArea to transparent, widgets inside lack their frames
-
Hi all,
"Is this a bug or a feature?!" – happens both with Qt 5.15.16 and Qt 6.8.2, using the Fusion style.
When I put a
QScrollArea
inside aQGroupBox
, the background is painted using a slightly lighter color than the group box's:
When I try to get id of this by explicitly setting the background to transparent, the different color is gone – but the widgets inside have their frames removed:
Cf. this minimal example:
#include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QGroupBox> #include <QScrollArea> #include <QLabel> #include <QPushButton> class Demo : public QWidget { public: Demo() { QVBoxLayout *layout; layout = new QVBoxLayout(this); auto *box = new QGroupBox(tr("Some Box")); layout->addWidget(box); layout = new QVBoxLayout(box); auto *scroll = new QScrollArea; scroll->setFrameShape(QFrame::NoFrame); layout->addWidget(scroll); // Uncomment to see the frames being gone //QPalette palette; //palette.setColor(QPalette::Window, Qt::transparent); //scroll->setPalette(palette); auto *widget = new QWidget; layout = new QVBoxLayout(widget); layout->addWidget(new QLabel(tr("Some Label"))); layout->addWidget(new QPushButton(tr("Some Button"))); scroll->setWidget(widget); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); Demo demo; demo.show(); return app.exec(); }
What's going on here?! How do I get rid of that different color without losing the frames?
-
@l3u_ said in When setting the background of a QScrollArea to transparent, widgets inside lack their frames:
What's going on here?!
I think the same color is used for the border and since you modified the palette it's also applied to the child widgets (ie. the button) of your scroll area.
-
Why would the
QPalette::Window
ColorRole be used for a border?! Also, the background color of theQGroupBox
is very different from the border color of theQPushButton
… -
See:
There is a limited amount of colors and settings in
QPalette
, so some controls/areas/widgets share the same role and therefore color.
The lighter color for group box also has to do with this.@l3u_ said in When setting the background of a QScrollArea to transparent, widgets inside lack their frames:
QPalette palette; palette.setColor(QPalette::Window, Qt::transparent); scroll->setPalette(palette);
You construct an empty palette here and only set the
QPalette::Window
role... other roles are undefined.
Specifying the role that is used for the button might solve this.Like
auto scrollPalette = scroll->palette(); scrollPalette.setColor(QPalette::Window, Qt::transparent); scroll->setPalette(scrollPalette);
-
Yeah, I read the docs … "QPalette::Window: 10 A general background color" … This is really weird …
However, one can work around this by setting the background (i.e.
QPalette::Window
) color toQt::transparent
and then set thestyle()->standardPalette()
for all widgets inside tol get the original look back. -
You construct an empty palette here and only set the
QPalette::Window
role... other roles are undefined.
Specifying the role that is used for the button might solve this.Using the scroll area's palette has the very same effect:
auto palette = scroll->palette(); palette.setColor(QPalette::Window, Qt::transparent); scroll->setPalette(palette);
-
Have you checked if
QPalette::Window
role is the correct role for your groupbox background?
MaybeMidlight
orLight
is used there and you only see the effect at first because you wiped the whole palette config for yourQScrollArea
? -
Well, at least, when setting the
QPalette::Window
color, the background of theQScrollArea
is painted using this very color – so I suppose it's the correct value.However, this seems to only affect Fusion. When e.g. using KDE's Breeze, the widgets inside are not affected in the same way. So I suppose I have to use the workaround I found (setting the style's default palette for all widgets inside).
-
Another update to this:
One can prevent this by setting
setAutoFillBackground(false)
, both for the scroll area'sviewport()
and the scroll widget set, after it has been set.
6/9