代码之家  ›  专栏  ›  技术社区  ›  user

何时在qt中使用paintevent和paintgl?

  •  1
  • user  · 技术社区  · 7 年前

    我正在使用 QOpenGLWidget 无法理解我应该在何处放置绘图代码:inside overriden paintGL 或内部重写 paintEvent .

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

    这些功能是如何连接的?paintgl启动paintevent还是反之?可能是由于不相交的原因(即恢复窗口、绘制一些三维几何图形、更改窗口大小)而启动的?那么这些原因是什么呢?

    最后,当我改变几何图形时,如何强制重新提交图形?我应该调用什么方法?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Scheff's Cat    7 年前

    简而言之:打开gl绘图 QOpenGLWidget 应该发生在 QOpenGLWidget::paintGL() .

    当调用opengl命令时,一个先决条件是resp。OpenGL上下文以前已激活。这是什么 QOpenGLWidget::paintGL() 确保:

    不用打电话 makeCurrent() 因为在调用此函数时已经执行了此操作。

    在调用此函数之前,将绑定上下文和帧缓冲区,并通过调用glviewport()来设置视口。

    另外一个先决条件是opengl上下文已经创建完毕。


    为了找到更多关于这个的信息,我深入了一点 QOpenGLWidget::paintEvent() (在woboq.org上):

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

    2. 绘制事件请求渲染。

    用眼睛看代码(严格地说:鼠标点击)。 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酒店 :

    如果需要从paintgl()以外的位置触发重绘(典型的例子是使用计时器设置场景动画),则应该调用小部件的 update() 函数来计划更新。


    万一,我误解了OP的意图,实际的问题是放在哪里 QPainter 并入 Qopenglwidget酒店 –我曾经给 SO: Paint a rect on qglwidget at specifit times 关于混合opengl命令和 Q画师 并入 paintGL() .