我正在使用QOpenGLWidget并且无法理解我应该在哪里放置绘图代码:内部覆盖paintGL或内部覆盖paintEvent。
我应该调用这些函数的基类版本吗?
这些功能是如何连接的? paintGL启动paintEvent,反之亦然?也许它们是由于非交叉原因(即恢复窗口,绘制一些3D几何图形,更改窗口大小)而启动的?那么这些原因是什么?
最后,当我更改几何体时,如何强制重新渲染图形?我应该用什么方法打电话?
答案 0 :(得分:3)
简短的回答:在QOpenGLWidget
中打开GL图纸QOpenGLWidget::paintGL()
。
当调用OpenGL命令时,前提条件是resp。之前已激活OpenGL上下文。这是QOpenGLWidget::paintGL()
确保的结果:
无需调用
makeCurrent()
,因为调用此函数时已经完成此操作。在调用此函数之前,绑定了context和framebuffer,并通过调用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();
}
只要尚未进行初始化,paint事件就不会执行任何操作。 (我没有深入挖掘,但我确信初始化涉及调用QOpenGLWidget::initializeGL()
。)
paint事件请求呈现。
按照眼睛的代码(严格地说:鼠标点击),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()以外的地方触发重绘(一个典型的例子是使用计时器为场景设置动画),你应该调用widget的
update()
函数来安排更新。
如果我误解了OP的意图,实际问题是QPainter
绘制QOpenGLWidget
的位置 - 我曾经写过SO: Paint a rect on qglwidget at specifit times关于混合OpenGL命令和QPainter
中的paintGL()
。