I have a simple widget which uses an image as background and contains some child widgets. When I create it without a parent (as a dialogue) everything is perfect. But if I create it as a child of some other widget, I can't see the background.
Can I use QWidget::setPalette to set the background for a child widget?
If not, how would you accomplish this?
#include <QWidget>
#include <QPixmap>
#include <QPalette>
#include <QLabel>
class Panel : public QWidget
{
Q_OBJECT
public:
explicit Panel(QWidget *parent = 0) QWidget(parent)
{
bgnd_ = new QPixmap(":/path/to/image.png");
PaintBackground();
QLabel* lbl = new QLabel("SomeChild",this);
}
private:
void PaintBackground()
{
QPixmap bgnd = bgnd_->scaled(this->size(), Qt::IgnoreAspectRatio);
QPalette palette;
palette.setBrush(QPalette::Background, bgnd);
this->setPalette(palette);
}
protected:
void resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
PaintBackground();
}
private:
QPixmap* bgnd_;
};
If I create this widget as an independent object with no parent, then it will render fine. I see the background and the child widget. If I create this widget as a child of another widget, then I see the lowest-level child, but the background is empty.
#include <QMainWindow>
#include "panel.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) :
QMainWindow(parent)
{
Panel* solo = new Panel();
solo->show();
Panel* child = new Panel(this);
}
};
The above class instantiates the widget in 2 ways: solo
gives me a dialogue with everything looking perfect. child
lets me see Panel
's child widgets, but the background is white.
Troubleshooting details
I thought this could be a bug in Qt as described here so I tried filtering out ThemeChange events by reimplementing the following in both Panel
and MainWindow
.
bool event(QEvent *event) override
{
if (event->type() != QEvent::ThemeChange)
{
return QWidget::event(event);
}
return true;
}
That didn't help.
Instead of painting my background with a QPalette
in resizeEvent
I found that the answer was to paint it with QPainter
in paintEvent
.
#include <QWidget>
#include <QPixmap>
#include <QPainter>
#include <QLabel>
class Panel : public QWidget
{
Q_OBJECT
public:
explicit Panel(QWidget *parent = 0) : QWidget(parent)
{
bgnd_ = new QPixmap(":/path/to/image.png");
QLabel* lbl = new QLabel("Hello",this);
}
protected:
void paintEvent( QPaintEvent* e )
{
QPainter painter( this );
painter.drawPixmap( 0, 0, bgnd_->scaled(size(), Qt::IgnoreAspectRatio));
QWidget::paintEvent( e );
}
private:
QPixmap* bgnd_;
};