1
votes

I would like to draw some overlay on my image viewer : a dashed rectangle around the image, indicating the bounding box. Here 's what I do in the paintEvent function:

void ViewerGL::paintEvent(QPaintEvent* event){
    makeCurrent();
    QPainter p(this);
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT); // << If I don't do this it clears out my viewer white
// and I want it black

    p.setBackgroundMode(Qt::TransparentMode); // < was a test, doesn't seem to do anything
    p.setBackground(QColor(0,0,0,0));

     //loading the appropriate shader before texture mapping
    if(rgbMode() && _shaderLoaded){
        shaderRGB->bind();
    }else if(!rgbMode() && _shaderLoaded){
        shaderLC->bind();
    }
    paintGL(); // render function (texture mapping)
    //drawing a rect around the texture on the viewer
    QPen pen(Qt::DashLine); 
    pen.setColor(QColor(233,233,233));
    p.setPen(pen);
    QPoint btmRight=mousePosFromOpenGL(dataWindow().w(),dataWindow().h() +transY*2 + ( zoomY-dataWindow().h()/2)*2);
    QPoint btmLeft=mousePosFromOpenGL(0,dataWindow().h() +transY*2 + ( zoomY-dataWindow().h()/2)*2);
    QPoint topLeft=mousePosFromOpenGL(0,0 +transY*2 + ( zoomY-dataWindow().h()/2)*2);
    QPoint topRight=mousePosFromOpenGL(dataWindow().w(), 0+ +transY*2 + ( zoomY-dataWindow().h()/2)*2);
    p.drawLine(topLeft,topRight);
    p.drawLine(topRight,btmRight);
    p.drawLine(btmRight,btmLeft);
    p.drawLine(btmLeft,topLeft);
    QPoint pos = mousePosFromOpenGL( (dataWindow().w()) + 10  ,
                                    (dataWindow().h()) +transY*2 + ( zoomY-dataWindow().h()/2)*2  +10); // bottom right of the texture +10
    p.drawText(pos, _resolutionOverlay);

    p.end();

}

And here is what I do in the paintGL function:

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

... my drawing code

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glPopAttrib();

And the initializeGL function :

    initAndCheckGlExtensions();
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glGenTextures (1, texId);
    glGenTextures (1, texBlack);

    glGenBuffersARB(1, &texBuffer);

    shaderBlack=new QGLShaderProgram(context());
    shaderBlack=new QGLShaderProgram(context());
    if(!shaderBlack->addShaderFromSourceCode(QGLShader::Vertex,vertRGB))
        cout << shaderBlack->log().toStdString().c_str() << endl;
    if(!shaderBlack->addShaderFromSourceCode(QGLShader::Fragment,blackFrag))
        cout << shaderBlack->log().toStdString().c_str() << endl;
    if(!shaderBlack->link()){
        cout << shaderBlack->log().toStdString().c_str() << endl;
    }

So far it works, I have what I want, but my program is flooding stderr on exit with : 'QGLContext::makeCurrent: Cannot make invalid context current'. I know this is coming from the QPainter and not from something else in my program.

I tried to move the code in the paintGL function to another function that is not virtual but that did not change anything.

1
Show us where you define the context.cmannett85
well the QGLContext object is created automatically with default settings, but here's the initialiazeGL function (in the main post)Lex

1 Answers

4
votes

You should first perform OpenGL calls, clear your OpenGL state, then wrap ALL QPainter draw calls between QPainter::begin(QGLWidget *) and QPainter::end(QGLWidget *).

Your program is most likely causing a problem because you interleave QPainter and OpenGL drawing calls. When you instantiate the QPainter object with QPainter(QPaintDevice *) you tell the QPainter to use the native drawing facilities of the QGLWidget to perform QPainter operations. So... QPainter uses OpenGL fixed-function calls to perform 2D drawing and it may interfere with your OpenGL rendering calls when your state has not been cleared.

I suggest following this guide:

https://doc.qt.io/archives/qt-4.8/qt-opengl-overpainting-example.html