Search code examples
qtqwidget

QWidget background images not appearing when parent exists


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.


Solution

  • 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_;
    };