PDA

View Full Version : [SOLVED] QGLWidget with QPainter commands: A drawing issue



Rayven
28th April 2011, 18:40
I am trying to overlay QPainter commands inside of a custom QGLWidget class, called Plot. The QGLWidget is currently all OpenGL commands, but I would like to utilize QPainter calls to draw annotations and 2D on-top of the 3D scene. Pan, zoom and stretch is handled by moving the viewport of the scene.


Please note that I hand-typed in this code and I cannot provide a compileable example.


Plot::Plot( QWidget *parent ) : QGLWidget( parent )
{
setAutoFillBackground( false );
setFocusPolicy( Qt::StrongFocus );
setAttribute( Qt::WA_OpaquePaintEvent, false );

// More attribute setup
}

void Plot::initializeGL()
{
QGLFormat myFormat = format();

myFormat.setDoubleBuffer( true );
myFormat.setOverlay( 0 );

// Specifying the rendering context for this plot
QGLContext *context = new QGLContext( myFormat );
context->create();
context->makeCurrent();
}

void Plot::paintEvent( QPaintEvent *event )
{
makeCurrent();

// Box zoom temporarily disables auto swap to XOR the draw line
if( (!mDrawBoxZoom || mDisableBox) && mScaleMode != G_SCALE )
{
// Ensure we are swapping buffers when not box zooming
setAutoBurrerSwap( true );
}

glMatrixMode( GL_MODELVIEW );
glPushMatrix();

glEnable( GL_SCISSOR_TEST );

int viewportLeft, viewportRight, viewportTop, viewportBottom;

// mpCoord is an object that contains the viewport, ortho and window heights for
// the entire Plot, so child object can position correctly.
glViewport( 0, 0, mpCoord->getWindowWidth(), mpCoord->getWindowHeight() );
glScissor( 0, 0, mpCoord->getWindowWidth(), mpCoord->getWindowHeight() );

qglClearColor( mBackgroundColor );

glClear( GL_COLOR_BUFFER_BIT );

// Clear the data section so each layer does not have to worry about
// whether it should perform the clearing or not
mpCoord->getViewport( viewportLeft, viewportRight, viewportBottom, viewportTop );

glViewport( viewportLeft, viewportBottom, viewportRight - viewportLeft,
viewportTop - viewportBottom );
glScissor( viewportLeft, viewportBottom, viewportRight - viewportLeft,
viewportTop - viewportBottom );

qglClearColor( mPlotBackgroundColor );
glClear( GL_COLOR_BUFFER_BIT );

if( !mDrawBoxZoom || mDisableBox || mScaleMode != G_SCALE )
{
// Draw each "Layer" of the Plot. Layers contain GL commands but are not
// QGLWidgets themselves
mpTitleLayer->paint();
mpAxisLayer->paint();
mpGridLayer->paint();
mpDataLayer->paint();
mpScaleLayer->paint();

//This code will eventually get put into QPainter commands, but for now, leave as is
mpAnnotationLayer->paint();
}

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho( mpCoord->getXMin(), mpCoord->getXMax(),
mpCoord->getYMin(), mpCoord->getYMax(),
mpCoord->getZMin(), mpCoord->getZMax() );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

glViewport( viewportLeft, viewportBottom, viewportRight - viewportLeft,
viewportTop - viewportBottom );
glScissor( viewportLeft, viewportBottom, viewportRight - viewportLeft,
viewportTop - viewportBottom );

if( mDrawBoxZoom && !mDisableBox )
{
drawBoxZoomXor();
}

glFlush();
glDisable( GL_SCISSOR_TEST );

// Ensure the state of the OpenGL
glMatrixMode( GL_MODELVIEW );
glPopMatrix();

// QPainter calls will go here, but not adding anything ATM
}

void Plot::resizeGL( int width, int height )
{
mpCoord->resize( width, height );

mpTitleLayer->resize( width, height );
mpAxisLayer->resize( width, height );
mpGridLayer->resize( width, height );
mpDataLayer->resize( width, height );
mpScaleLayer->resize( width, height );
}


I have followed the Overpainting example as best I could and from my understanding the "only" changes I should have to make to my class is to change paintGL to paintEvent(QPaintEvent*), put all QPainter commands after the OpenGL commands, and pop the matrix stack at the end.

With these changes to my Plot, the initial image appears just fine, however the mousePressEvent, mouseMoveEvent and mouseReleaseEvents flickers HORRIBLY and the plot does not actually "move". All the values used to change the viewport variables are being set properly, but the image is not changing (the paintEvent is not being called). If I use QGLWidget::update() (http://doc.qt.nokia.com/latest/qglwidget.html#update)instead of QGLWidget::updateGL() (http://doc.qt.nokia.com/latest/qglwidget.html#updateGL) during the mouse functions, the paintEvent is called, but only a white scene appears.

Any thoughts or ideas?

Qt v4.7.2
VS2008 SP1

Added after 1 39 minutes:

Well apparently you have to call update(), not updateGL() AND have QPainter code at the end. No QPainter calls, nothing paints! Hope this helps someone else from loosing hair!