我正在使用QOpenGLWidget,无法理解应将绘图代码放在哪里:重写paintGL内或重写paintEvent内。

我应该调用这些函数的基类版本吗?

这些功能如何连接? paintGL启动paintEvent还是反之?也许是由于非相交的原因(例如,还原窗口,绘制一些3D几何形状,更改窗口大小)而启动的吗?这些原因是什么?

最后,当我更改几何图形时如何强制重新渲染图形?我应该叫什么方法?

最佳答案

简短的答案:在QOpenGLWidget中打开GL绘图应该在QOpenGLWidget::paintGL()中进行。

当调用OpenGL命令时,先决条件是响应。 OpenGL上下文已被激活。这是 QOpenGLWidget::paintGL() 确保的:



顺便说一句。另一个前提条件是响应。 OpenGL上下文已全部创建。

为了了解更多信息,我在 QOpenGLWidget::paintEvent() (在woboq.org上)进行了更深入的研究:

void QOpenGLWidget::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e);
    Q_D(QOpenGLWidget);
    if (!d->initialized)
        return;
    if (updatesEnabled())
        d->render();
}
  • 只要尚未完成初始化,paint事件就不会执行任何操作。 (我没有深入研究,但是我确定初始化涉及对QOpenGLWidget::initializeGL()的调用。)
  • 绘画事件要求渲染。

  • 通过眼睛跟踪代码(严格来说:单击鼠标),d->render()调用QOpenGLWidgetPrivate::render(),然后依次调用QOpenGLWidgetPrivate::invokeUserPaint(),这里是:
    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;
    }
    

    (评论是我的。)

    因此,如果QOpenGLWidget::paintEvent()重载,则应调用基类的paintEvent()。 (否则,OpenGL渲染肯定会中断。​​)



    这实际上在QOpenGLWidget的描述中得到了回答:



    以防万一,我误解了OP的意图,而实际的问题是将QPainter绘图放置在QOpenGLWidget中的位置–我曾经为SO: Paint a rect on qglwidget at specifit times编写了关于将OpenGL命令和QPainter绘图混合在paintGL()中的答案。

    关于c++ - 何时在Qt中使用paintEvent和paintGL?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50855257/

    10-11 19:05