4
votes

I need to create an alpha transparent widget, it's basically a navigation bar with a shadow and the widgets below need to be partially visible through the shadow. The widget loads a PNG then draws it on the paint event. The problem is that the shadow is all black and is not alpha-transparent.

This is the code I'm currently using:

NavigationBar::NavigationBar(QWidget *parent) : XQWidget(parent) {
    backgroundPixmap_ = new QPixmap();
    backgroundPixmap_->load(FilePaths::skinFile("NavigationBarBackground.png"), "png");

    setAttribute(Qt::WA_NoBackground, true); // This is supposed to remove the background but there's still a (black) background
}


void NavigationBar::paintEvent(QPaintEvent* event) {
    QWidget::paintEvent(event);

    QPainter painter(this);
    int x = 0;
    while (x < width()) {
        painter.drawPixmap(x, 0, backgroundPixmap_->width(), backgroundPixmap_->height(), *backgroundPixmap_);
        x += backgroundPixmap_->width();
    }
}

Does anybody know what I need to change to make sure the widget is really transparent?

2

2 Answers

1
votes

You're doing too much work :-)

The setAttribute call is not necessary. By default, a widget will not draw anything on its background (assuming Qt >= 4.1). Calling QWidget::paintEvent is also unnecessary - you don't want it to do anything.

Rather than doing the pattern fill yourself, let Qt do it with a QBrush:

NavigationBar::NavigationBar(QWidget *parent) : XQWidget(parent) {
    backgroundPixmap_ = new QPixmap();
    backgroundPixmap_->load(FilePaths::skinFile("NavigationBarBackground.png"), "png");
    // debug check here:
    if (!backgroundPixmap_->hasAlphaChannel()) {
      // won't work
    }
}


void NavigationBar::paintEvent(QPaintEvent* event) {
    QPainter painter(this);
    painter.fillRect(0, 0, width(), height(), QBrush(*backgroundPixmap));
}    

Adjust the height parameter if you don't want the pattern to repeat vertically.

0
votes

Are you sure your PNG file is actually transparent? The following (which is essentially what you are doing) is working for me. If this fails on your machine, perhaps include what version of Qt you are using, and what platform.

#include <QtGui>

class TransparentWidget : public QWidget {
public:
  TransparentWidget()
    : QWidget(),
      background_pixmap_(":/semi_transparent.png") {
    setFixedSize(400, 100);
  }
protected:
  void paintEvent(QPaintEvent *) {
    QPainter painter(this);
    int x = 0;
    while (x < width()) {
      painter.drawPixmap(x, 0, background_pixmap_);
      x += background_pixmap_.width();
    }
  }
private:
  QPixmap background_pixmap_;
};

class ParentWidget : public QWidget {
public:
  ParentWidget() : QWidget() {
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(new TransparentWidget);
    layout->addWidget(new QPushButton("Button"));
    setLayout(layout);
    setBackgroundRole(QPalette::Dark);
    setAutoFillBackground(true);
  }
};

int main(int argc, char **argv) {
  QApplication app(argc, argv);
  ParentWidget w;
  w.show();
  return app.exec();
}