PDA

View Full Version : qglwidget overpaint



Cruz
10th May 2019, 11:31
Hi there,

I would like to achieve what is being done in the overpaint example (http://libqglviewer.com/examples/overpainting.html) of QGLViewer: render a 3D scene with OpenGL and paint something *on top* of that with a QPainter. I followed the instructions on that website and did this:



class OpenGLWidget: public QGLViewer
{
Q_OBJECT

public:
OpenGLWidget(QWidget* parent=0);
~OpenGLWidget();

protected:
void paintEvent(QPaintEvent *event); // override paintEvent

};

OpenGLWidget::OpenGLWidget(QWidget *parent) : QGLViewer(parent)
{
setAttribute(Qt::WA_NoSystemBackground);
}

void OpenGLWidget::paintEvent(QPaintEvent *event)
{
QGLViewer::paintEvent(event); // Do what the overridden method would do.

// Paint something with QPainter.
QPainter painter;
painter.setBackgroundMode(Qt::TransparentMode);
painter.begin(this); // This is where it happens.
painter.setPen(colorUtil.penBlueThick);
painter.drawLine(0, 0, 100, 100);
}



Unfortunately this does not have the desired effect. When I begin() the painter, the background is cleared and the 3D rendering disappears. Setting the background mode to transparent, and setting the widget attribute to NoSystemBackground have no effect. Can anyone help me along please?

Thanks
Cruz

Cruz
10th May 2019, 13:44
Good, by now I managed to make it work like this:



void OpenGLWidget::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);

// Save current OpenGL state
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

// Setup OpenGL context.
setBackgroundColor(QColor(255,255,255));
setForegroundColor(QColor(0,0,0));
setFont(QFont("Helvetica", 18));
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

drawOpenGL(); // draw a bunch of opengl things

// Restore OpenGL state
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();

drawOverPaint(&painter); // 2D QPainter drawing

painter.end();
}


What I don't understand is, on one computer this works perfectly and the QPainter code is drawn over the OpenGL, on another computer the OpenGL is on top of the QPainter drawing and covers it fully.
How do I have control over what gets painted over what?

d_stranz
10th May 2019, 18:43
QGLViewer is derived from QOpenGLWidget. See the docs for that class on how to combine QPainter and OpenGL in a single paint event:



It is also possible to draw 2D graphics onto a QOpenGLWidget subclass using QPainter:

- In paintGL(), instead of issuing OpenGL commands, construct a QPainter object for use on the widget.
- Draw primitives using QPainter's member functions.
- Direct OpenGL commands can still be issued. However, you must make sure these are enclosed by a call to the painter's beginNativePainting() and endNativePainting().

The order in which you do this would likely affect which graphics are "on top". You may not have to do all of the state saving / restoring.