升级Qt6后QOpenGLContext调用非OpenGL表面报错及UI异常
问题概述
- 环境配置:
- Ubuntu 24.04
- OCC 7.8.1
- Qt 6.4.2
- 场景:QTabWidget包含两个标签页,第一个关联QPushButton,第二个关联继承自QOpenGLWidget的OccQtViewer(承载OCC渲染逻辑)
- 问题:切换到第二个标签页后UI混乱、标签无响应,控制台输出警告:
QOpenGLContext::makeCurrent() called with non-opengl surface 0x5c468b22deb0 QRhiGles2: Failed to make context current. Expect bad things to happen. - 对比情况:Windows+Qt6、Linux+Qt5下运行正常,仅Linux+Qt6出现问题;尝试过设置窗口SurfaceType但未解决。
解决方案
针对Linux下Qt6与OCC的OpenGL上下文冲突问题,可按以下步骤修复:
1. 提前设置主窗口的Surface类型
在窗口显示前,强制将主窗口的Surface设置为OpenGL类型,避免Qt默认使用其他渲染后端:
int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; if (w.windowHandle()) { w.windowHandle()->setSurfaceType(QWindow::OpenGLSurface); } w.show(); return a.exec(); }
2. 管控OpenGLWidget的上下文生命周期
重写OccQtViewer的showEvent和hideEvent,确保切换标签时上下文正确激活/释放:
void OccQtViewer::showEvent(QShowEvent* event) { QOpenGLWidget::showEvent(event); if (context()) { context()->makeCurrent(this); if (myView) { myView->Redraw(); } context()->doneCurrent(); } } void OccQtViewer::hideEvent(QHideEvent* event) { QOpenGLWidget::hideEvent(event); if (context()) { context()->doneCurrent(); } }
3. 强制Qt6使用OpenGL后端
在main函数开头添加环境变量,禁用Qt6默认的非OpenGL渲染后端:
int main(int argc, char *argv[]) { qputenv("QT_OPENGL", "desktop"); qputenv("QT_QUICK_BACKEND", "opengl"); QApplication a(argc, argv); MainWindow w; // ...后续代码 }
4. 延迟OCC初始化到OpenGL上下文就绪后
将OCC的视图初始化逻辑从OccQtViewer的构造函数移到initializeGL中,确保在OpenGL上下文完全创建后再初始化OCC资源:
void OccQtViewer::initializeGL() { QOpenGLWidget::initializeGL(); Handle(Aspect_DisplayConnection) displayConn; myContext = new V3d_Viewer(displayConn); myView = myContext->CreateView(); myView->SetBackgroundColor(Quantity_NOC_GRAY); // 其他OCC初始化操作... }
问题原因
Qt6在Linux平台默认可能采用Vulkan或其他非OpenGL渲染后端,导致QOpenGLWidget的上下文与窗口Surface不兼容;同时QTabWidget切换时,OpenGLWidget的上下文未被正确管理,OCC的渲染逻辑尝试在无效上下文下执行,引发UI异常。
内容的提问来源于stack exchange,提问作者Alex Luya
相关产品推荐
相关产品推荐

