How to clear the background of a QOpenGLWidget?
-
I have succeeded in clearing the background of a
QOpenGLWidget
only after callingsetAttribute(Qt::WA_AlwaysStackOnTop);
however, as the name describes, the widgets become on top of other widgets.I also tried:
initializeOpenGLFunctions(); this->glClearColor(0.0, 0.0, 0.0, 0.0);
But the background also didn't get 'cleared'.
#include <qopenglwidget.h> #include <qopenglfunctions.h> class OpenGL : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: QImage image; OpenGL(QWidget* parent = NULL) : QOpenGLWidget(parent) { //setAutoFillBackground(false); //setAttribute(Qt::WA_AlwaysStackOnTop); QGridLayout* layout = new QGridLayout(this); this->setLayout(layout); QPushButton* btn = new QPushButton(this); btn->setGeometry(100, 100, 300, 50); btn->setStyleSheet("background-color: red;"); btn->setText("test"); layout->addWidget(btn); }; void initializeGL() { initializeOpenGLFunctions(); this->glClearColor(0.0, 0.0, 0.0, 0.0); if (!image.load(":/logos/dr_logo")) qDebug() << "Failed to load the image."; }; void paintGL() { if (image.isNull()) return; QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QRect area = this->rect(); p.drawImage(area, image, image.rect()); }; //void resizeGL(int width, int heigh) //{ //}; };
Also, isn't possible to add widgets to an
OpenGLWidget
in theQt Designer
? -
glClearColor
only sets a color that would be used for clearing. To actually clear the background callglClear(GL_COLOR_BUFFER_BIT);
at the start of
paintGL
function. This will clear the color buffer. You can also clear depth and stencil buffers if you have those enabled withGL_DEPTH_BUFFER_BIT
andGL_STENCIL_BUFFER_BIT
. -
glClearColor
only sets a color that would be used for clearing. To actually clear the background callglClear(GL_COLOR_BUFFER_BIT);
at the start of
paintGL
function. This will clear the color buffer. You can also clear depth and stencil buffers if you have those enabled withGL_DEPTH_BUFFER_BIT
andGL_STENCIL_BUFFER_BIT
.@Chris-Kawa said in How to clear the background of a QOpenGLWidget?:
glClear(GL_COLOR_BUFFER_BIT);
The background continues black, tried single and both options
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I'm missing anything else? and about the Qt Designer thing?
-
@Chris-Kawa said in How to clear the background of a QOpenGLWidget?:
glClear(GL_COLOR_BUFFER_BIT);
The background continues black, tried single and both options
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I'm missing anything else? and about the Qt Designer thing?
The background continues black
this->glClearColor(0.0, 0.0, 0.0, 0.0);
is a black color so yeah, you're gonna have it clear to black. If you want it for example white set the clear color to all ones.and about the Qt Designer thing?
QOpenGLWidget creates a native window for OpenGL painting on top of the widget. You can't have another widget on top of that. All widgets are below it.
-
The background continues black
this->glClearColor(0.0, 0.0, 0.0, 0.0);
is a black color so yeah, you're gonna have it clear to black. If you want it for example white set the clear color to all ones.and about the Qt Designer thing?
QOpenGLWidget creates a native window for OpenGL painting on top of the widget. You can't have another widget on top of that. All widgets are below it.
@Chris-Kawa said in How to clear the background of a QOpenGLWidget?:
The background continues black
this->glClearColor(0.0, 0.0, 0.0, 0.0);
is a black color so yeah, you're gonna have it clear to black. If you want it for example white set the clear color to all ones.I have removed this line. The background continued black.
class OpenGL : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: QImage image; OpenGL(QWidget* parent = NULL) : QOpenGLWidget(parent) { //setAutoFillBackground(false); //setAttribute(Qt::WA_AlwaysStackOnTop); //setAttribute(Qt::WA_TranslucentBackground); QGridLayout* layout = new QGridLayout(this); this->setLayout(layout); QPushButton* btn = new QPushButton(this); btn->setGeometry(100, 100, 300, 50); btn->setStyleSheet("background-color: red;"); btn->setText("test"); layout->addWidget(btn); }; void initializeGL() { initializeOpenGLFunctions(); //glClearColor(0.0, 0.0, 0.0, 100); //glClear(GL_COLOR_BUFFER_BIT); if (!image.load(":/sw_logos/sw_logo1")) qDebug() << "Failed to load the image."; }; void paintGL() { //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT); if (image.isNull()) return; QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QRect area = this->rect(); p.drawImage(area, image, image.rect()); }; };
-
I have removed this line. The background continued black.
Because black is also the default. Changing black to black doesn't change anything :)
Don't removeglClearColor
. Set it to color that you want to clear to. For example if you want a red background it'sglClearColor(1.0, 0.0, 0.0, 1.0)
. -
I have removed this line. The background continued black.
Because black is also the default. Changing black to black doesn't change anything :)
Don't removeglClearColor
. Set it to color that you want to clear to. For example if you want a red background it'sglClearColor(1.0, 0.0, 0.0, 1.0)
.@Chris-Kawa i'm trying to get the openglwidget background transparent, is it possible?
-
@Chris-Kawa i'm trying to get the openglwidget background transparent, is it possible?
It depends on couple different factors, including your OS and window manager. See Limitations and Other Considerations.
-
The OS is Windows 10, i read the doc you sent, and after setting
setAttribute(Qt::WA_TranslucentBackground);
to the parent window
the OpenGLWidget background also got transparent.However, which
setAttribute(Qt::WA_TranslucentBackground);
turned on the GUI is using 3x more CPU for simple tasks like moving around the screen.Why this option is so 'evil' in resource usage? it transform the window in a layered window?
Also, why the image draw in the
paintGL
has a very lower quality compared to when drawn directly into aQWidget
? -
The OS is Windows 10, i read the doc you sent, and after setting
setAttribute(Qt::WA_TranslucentBackground);
to the parent window
the OpenGLWidget background also got transparent.However, which
setAttribute(Qt::WA_TranslucentBackground);
turned on the GUI is using 3x more CPU for simple tasks like moving around the screen.Why this option is so 'evil' in resource usage? it transform the window in a layered window?
Also, why the image draw in the
paintGL
has a very lower quality compared to when drawn directly into aQWidget
?@Kattia said in How to clear the background of a QOpenGLWidget?:
However, which setAttribute(Qt::WA_TranslucentBackground); turned on the GUI is using 3x more CPU for simple tasks like moving around the screen.
Here is my (uninformed) guess: If you have an opaque background you just clear the OpenGL canvas, then paint on it an finally draw it on the screen. The last step is just a simple swap of the buffers (and maybe additional blitting). This is all relatively fast. With a transparent background you first need to get a picture from the desktop in the OpenGL drawing area. This is now first set as the background of the OpenGL canvas and only after that you paint on the canvas and draw it on the screen.
Especially when moving widgets around this will have a huge impact: Windows is optimized for opaque widgets to just move the picture around without painting anything new. However, with a transparent background you always have to repaint the whole widget for every single pixel moved. So, this has to run through the whole OpenGL painting again.
One thing you can try to speed this up is to use masking for the fully transparent parts of your widgets (like so: https://doc.qt.io/qt-6/qtwidgets-widgets-shapedclock-example.html). You could use OpenGL with a special buffer to write the mask. I am not sure if this helps at all. It certainly only works when there is nothing partially transparent in your OpenGL paintings.
@Kattia said in How to clear the background of a QOpenGLWidget?:
Also, why the image draw in the paintGL has a very lower quality compared to when drawn directly into a QWidget ?
Most likely because Qt uses anti aliasing. You need to use something like super sampling or similar techniques in OpenGL to have a better quality.
-
@SimonSchroeder said:
With a transparent background you first need to get a picture from the desktop in the OpenGL drawing area. This is now first set as the background of the OpenGL canvas and only after that you paint on the canvas and draw it on the screen
That's not how it works. Each window is drawn to its own buffer with alpha information. A window manager then takes these buffers and composes them in z-order. Depending on the window manager implementation and type of the window it's possible that a GPU readback to the main memory is needed for the composition and that could be what's eating up CPU. In general hardware accelerated transparent surfaces are not very efficient.