首页 > 解决方案 > QOpenGLWidget 的上下文为空

问题描述

我正在尝试添加一个QOpenGLWidget到我的QGraphicsScene,但是当我调用时应用程序崩溃了initializeOpenGLFunctions()。我很确定上下文OpenGLView为空,这就是为什么它崩溃(不提供日志)的原因有两个:

  1. 当我打印它时,它会输出0x0
  2. 当我尝试启用QOpenGLDebugLogger它时,输出没有当前上下文。

我认为 QOpenGLWidget 会有一个开箱即用的 OpenGLContext 。知道为什么没有设置上下文吗?我在初始化中遗漏了什么吗?

QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setOption(QSurfaceFormat::DebugContext);
QSurfaceFormat::setDefaultFormat(format);


OpenGLView view = new OpenGLView();

标题

class OpenGLView : public QOpenGLWidget, protected QOpenGLFunctions
{
}
#include "OpenGLView.h"

OpenGLView::OpenGLView(QWidget *parent) : QOpenGLWidget(parent) {
    initializeGL();
}


void OpenGLView::initializeGL() {
    initializeOpenGLFunctions(); // crashes
//    ...
}

void OpenGLView::paintGL() {
//    ...
}

void OpenGLView::resizeGL(int w, int h) {
//    ...
}

标签: qtopenglqml

解决方案


这是因为你initializeGL()在构造函数中调用了。到那时,上下文尚未初始化。显示小部件时首先初始化上下文。以下详细信息来自Qt 的源代码

void QOpenGLWidgetPrivate::initialize()
{
    Q_Q(QOpenGLWidget);
    if (initialized)
        return;
    
    ...

    QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
    ctx->setFormat(requestedFormat);
    if (shareContext) {
        ctx->setShareContext(shareContext);
        ctx->setScreen(shareContext->screen());
    }
    if (Q_UNLIKELY(!ctx->create())) {
        qWarning("QOpenGLWidget: Failed to create context");
        return;
    }

    ...

    context = ctx.take();
    initialized = true;
    q->initializeGL();
}

bool QOpenGLWidget::event(QEvent *e)
{
    Q_D(QOpenGLWidget);
    switch (e->type()) {

    ...

    case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
        if (d->initialized && window()->windowHandle()
                && d->context->shareContext() != QWidgetPrivate::get(window())->shareContext())
        {
            // Special case: did grabFramebuffer() for a hidden widget that then became visible.
            // Recreate all resources since the context now needs to share with the TLW's.
            if (!QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts))
                d->reset();
        }
        if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
            d->initialize();
            if (d->initialized)
                d->recreateFbo();
        }
        break;

    ...

    }
    return QWidget::event(e);
}

推荐阅读