QOpenGLWidget 的上下文为空

Posted

技术标签:

【中文标题】QOpenGLWidget 的上下文为空【英文标题】:QOpenGLWidget's context is null 【发布时间】:2020-11-09 01:38:22 【问题描述】:

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

    当我打印它时,它输出0x0 当我尝试启用 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) 
//    ...


【问题讨论】:

可能是很多事情,比如不支持 GL 3.2 我确实支持 GL 3.2。除了 QT 之外,该版本一直在使用 OpenGL。 OpenGLView 不继承 QOpenGLFunctionsinitializeOpenGLFunctions() 函数在哪里? 确实如此,我更新了我的代码 【参考方案1】:

这是因为你在构造函数中调用了initializeGL()。到那时,上下文还没有初始化。显示小部件时首先初始化上下文。详情取自以下Qt's source code:

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);

【讨论】:

这有帮助,我现在得到一个非空上下文,但在调用 initializeOpenGLFunctions 时仍然崩溃 调试器这次说什么? 同样的事情“程序意外结束。” 已解决 - 有一个 nullptr 需要一些时间才能找到。

以上是关于QOpenGLWidget 的上下文为空的主要内容,如果未能解决你的问题,请参考以下文章

错误:试图在空上下文对象上调用方法“格式”

错误:尝试在空上下文中调用方法 isEmpty

在 android 中使用 Telr 支付网关时上下文为空

PySide2 QOpenGLWidget 按键事件不起作用

在android中获取上下文和活动对象null

.NET 6新特性试用 | 可空引用类型