c++qttransparentqwidgetqframe

Qt - Draw a fully transparent window in Windows without using WA_TranslucentBackground


I need to draw transparent window (either QLabel or QFrame or QWidget), but without using WA_TranslucentBackground. The reason for that is that the windows will contain other child widgets rendered through OpenGL, and using that property makes those windows invisible on Windows, as documented here. This works fine in Mac though, I need a different solution on Windows only, as it does not work there. I tried this: setting a blank pixmap. But it still shows up with a grey background:

#include <QApplication>
#include <QLabel>
#include <QBitmap>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLabel l;
    l.setWindowFlags(Qt::FramelessWindowHint);
    QPixmap p("");
    l.setPixmap(p);
    l.setScaledContents(true);
    l.resize(300, 500); //just to test my idea
    l.setMask(p.scaled(l.width(),l.height(),Qt::IgnoreAspectRatio,
    Qt::SmoothTransformation).mask());
    l.show();
    return a.exec();
}

Can anyone suggest any other means of achieving this on Windows, i.e a fully transparent window? Platform - Qt 5.3.1, 32 bit.

P.S - It need not behave like translucent window, i.e where the background can be clicked through the transparent parts of a widget rendered though WA_TranslucentBackground. Here as long as it is transparent it will be okay, it need not be clickable 'through'.


Solution

  • Unfortunately this is not possible on Windows. You can set transparency for widget with color with alpha-channel like this: setStyleSheet("background-color: rgba(255,0,0,50%);");. But whis is doesn't work for top level widget until you set WA_TranslucentBackground. Without this flag alpha-channel doesn't work and you get black window. So the only solution is use WA_TranslucentBackground. And then do OpenGL painting like Qt documentation says:

    To work around this issue you can either just use Qt to render everything and not OpenGL, or you can render the OpenGL into a pixmap and draw that onto your widget instead.