相关文章推荐
难过的盒饭  ·  recyclerview 横滑 item ...·  2 月前    · 
纯真的冲锋衣  ·  Eclipse RCP: ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am using QOpenGLWidget and can't understand where should I put drawing code: inside overriden paintGL or inside overriden paintEvent .

Should I call base class versions of these functions?

How these functions are connected? paintGL launches paintEvent or vice-versa? Maybe they launch as a result of non intersecting reasons (i.e. restore window, draw some 3D geometry, change window size)? What are these reasons then?

Finally, how to force rerender of graphics when I change geometry? What method should I call?

The short answer: Open GL drawing in QOpenGLWidget should happen in QOpenGLWidget::paintGL() .

When OpenGL commands shall be called, a pre-condition is that the resp. OpenGL context has been activated before. This is what QOpenGLWidget::paintGL() ensures:

There is no need to call makeCurrent() because this has already been done when this function is called.

Before invoking this function, the context and the framebuffer are bound, and the viewport is set up by a call to glViewport().

Btw. another pre-condition is that the resp. OpenGL context has been created at all.

To find out more about this I digged a bit deeper – in QOpenGLWidget::paintEvent() (on woboq.org):

void QOpenGLWidget::paintEvent(QPaintEvent *e)
    Q_UNUSED(e);
    Q_D(QOpenGLWidget);
    if (!d->initialized)
        return;
    if (updatesEnabled())
        d->render();
  • The paint event does nothing as long as initialization is not yet done. (I didn't dig deeper but I'm sure that initialization involves calling of QOpenGLWidget::initializeGL().)

  • The paint event requests rendering.

  • Following the code by eyes (stricly speaking: mouse clicks), d->render() calls QOpenGLWidgetPrivate::render() which in turn calls finally QOpenGLWidgetPrivate::invokeUserPaint() and here we are:

    void QOpenGLWidgetPrivate::invokeUserPaint()
        Q_Q(QOpenGLWidget);
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
        Q_ASSERT(ctx && fbo);
        QOpenGLFunctions *f = ctx->functions();
        QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = fbo->handle();
        f->glViewport(0, 0, q->width() * q->devicePixelRatioF(), q->height() * q->devicePixelRatioF());
        inPaintGL = true;
     // vvvvvvvvvvvv
        q->paintGL();
     // ^^^^^^^^^^^^
        inPaintGL = false;
        flushPending = true;
        QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = 0;
    

    (The comments are mine.)

    So, if QOpenGLWidget::paintEvent() is overloaded then it should call the paintEvent() of base class. (Otherwise, the OpenGL rendering will certainly break.)

    Finally, how to force rerender of graphics when I change geometry? What method should I call?

    This is actually answered in the description on QOpenGLWidget:

    If you need to trigger a repaint from places other than paintGL() (a typical example is when using timers to animate scenes), you should call the widget's update() function to schedule an update.

    Great answer! Now it is clear that when I want to redraw my geometry I can simply call update(), it will call paintEvent(), which finally will call paintGL(). – user8044236 Jun 14, 2018 at 12:41 Yepp, exactly. I was just about to add this part. And it does also mean that window resizing, overlapping, etc. should force updates as well (as usual). – Scheff's Cat Jun 14, 2018 at 12:43

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.