I am trying to use QLabel
as a powerful tool to render some text with CSS into a texture. After I obtain an image, a texture is formed in OpenGL and the original Qt object is discarded. Afterwards I use the texture as any other texture in plain OpenGL (without Qt) rendering pipeline.
However, I am having problems handling the transparency of the background. Something - probably some Qt setting that I am not aware of - seems to be messing up my settings.
After a bit of simplification, my texture is produced like this:
QLabel label;
label.setAttribute(Qt::WA_TranslucentBackground, true);
const QString styleSheet{"color : #00bbbb; background-color : rgba(0,0,0,0);"
"font-family: 'Calibri'; text-decoration: none; margin: 5px;"};
label.setWordWrap(true);
label.setAutoFillBackground(false);
label.setStyleSheet(styleSheet);
QFont font = label.font();
font.setPointSizeF(12.0f);
label.setFont(font);
// set text
label.setText(QString("The quick brown fox jumps over the lazy dog"));
// render
label.adjustSize();
label.updateGeometry();
std::unique_ptr<QImage> imgTexture = std::make_unique<QImage>(label.size(), QImage::Format_RGBA8888);
QPainter painter(imgTexture.get());
label.render(&painter);
uint8_t *bits = imgTexture->bits();
std::cout << int(bits[0]) << " " << int(bits[1]) << " " << int(bits[2]) << " " << int(bits[3]) << std::endl;
The output - the value of the top-left pixel of the produced image - is:
205 205 205 205
and not 0 0 0 0 as I expected. Thus, the problem is already at this point and not later in my OpenGL handling of the texture. Ultimately my output is:
As seen, the background is not entirely transparent as expected.
Update
As per G.M.'s suggestion I tried setCompositionMode
(with no effect), but also other painter settings. Apparently setting QPainter::setBackgroundMode
to Qt::OpaqueMode
steps one step further:
The Qt manual says:
Qt::TransparentMode (the default) draws stippled lines and text without setting the background pixels. Qt::OpaqueMode fills these space with the current background color.
so, it seems the default is to not change the original pixels of the output image anywhere where letters are not present. So, the transparent (0,0,0,0) is not drawn, and the previous color (apparently 205, 205, 205, 205 for some reason) remains unchanged.
Forcing drawing the background updates all pixels but only in the neighbourhood of the letters. I now need to figure out how to force clearing all pixels to the color specified in CSS.
Update Apparently it is not as simple as it seems. I tried painter.eraseRect(0, 0, width, height);
but this clears the rectangle into white, ignoring the CSS settings.