PDA

View Full Version : Semi-transparent widgets on top of QGLWidget



GdelP
1st August 2013, 09:04
I am developing an application consisting in a QGLWidget and several buttons on top of it. It works fine on Windows/Linux when the buttons are square.

However, when I try to make part of the button widget transparent (background, rounded borders) I get pure black instead of transparent.

I've been seraching for several days. I found two solutions:
-Render in another buffer, grab its content and render it as a QImage into a QWidget.
-Use QGraphicsView (http://doc.qt.digia.com/qq/qq26-openglcanvas.html)

First option is not applicable due to heavy real-time restrictions. I render heavy 3D data with heavy post-effects. The overhead involved in copying a buffer is not acceptable, since I am also targetting mid-end to low-end computers.
Second option seems to be outdated. I only could find examples that do not even compile with Qt5. Is it still aplicable? Does it work the same way? Is there any tutorial or code example on the topic?
Also, documentation suggests that it's designed for efficiently drawing lots of widgets. Is it still applicable to my case? Has it evolved since then?

wysota
1st August 2013, 09:15
You get black because the GL widget does not use the backing store and thus when a semi-transparent button is drawn, the backing store content "behind" it is black and that's what you get. A solution would be to implement your buttons in OpenGL (you can use QPainter calls to draw it as usual, the idea is that the buttons can't be separate widgets but have to be drawn directly over the gl widget) as well or to try running the whole application with "-graphicssystem opengl" parameter. With Qt5 you have some more options regarding this, including implementing your UI in QtQuick (e.g, using QtQuickControls) and painting the GL scene using beforeRendering() signal.

GdelP
1st August 2013, 11:02
I understand the reason why transparency is not handled correctly. Thanks!

Implementing my buttons in OpenGL means reimplementing rendering and event handling. That's to say, it's not enough drawing my buttons, I need them to be clicked, highlighted by tab and so on. I want to focus myself on my application, not on re-implementing a widget engine. That's the reason I chose Qt initially.

Running the whole application with "-graphicssystem opengl" does not change anything. In fact, documentation (http://qt-project.org/doc/qt-5.1/qtwidgets/qapplication.html#QApplication) says nothing about that option. It doesn't work, but, even if it did, I do not want to depend on undocumented features. Googling also gives no information about it in Qt5.

Changing to QtQuick is not possible at this time. I have logic involving creation/destruction/modification of custom QWidgets that can't be embedded in QtQuick (http://stackoverflow.com/questions/13014415/qt5-embed-qwidget-object-in-qml). However, it seems the best option.


I think I will stick to QWidgets and not use transparency by now.


Thanks for your time!

wysota
1st August 2013, 11:07
Running the whole application with "-graphicssystem opengl" does not change anything. In fact, documentation (http://qt-project.org/doc/qt-5.1/qtwidgets/qapplication.html#QApplication) says nothing about that option. It doesn't work, but, even if it did, I do not want to depend on undocumented features. Googling also gives no information about it in Qt5.
It's a Qt4 feature, I didn't notice you were using Qt5.



Changing to QtQuick is not possible at this time. I have logic involving creation/destruction/modification of custom QWidgets that can't be embedded in QtQuick (http://stackoverflow.com/questions/13014415/qt5-embed-qwidget-object-in-qml). However, it seems the best option.

Often it is just enough to change the base class for your class from QWidget to QQuickPaintedItem and adjust the code to the new base class.

nvd291
1st August 2013, 17:19
It is impossible to do it with QGLWidget without doing a workaround. (QT says it itself, I read it somewhere when I was looking for a solution myself)
I wrote a class (attached) for a European research project and so far it worked perfectly for me.

All you need to do is to subclass it and set the widget that you want to be overlayed as background. (see the main.cpp file I have attached)

Hope it helps!

wysota
1st August 2013, 19:06
I think it is much more efficient (and easier) to render the scene to an FBO, convert it to a QImage and paint on a regular raster widget.