如何强制Qt默认使用OpenGL窗口类型?解决动态添加控件重启问题
Qt文档指出:
当在部件层级中动态添加QOpenGLWidget时,例如将新的QOpenGLWidget作为已显示在屏幕上的顶级部件的子部件,若该QOpenGLWidget是窗口内首个此类部件,关联的原生窗口可能会被隐式销毁并重建。这是因为窗口类型从RasterSurface变为OpenGLSurface,而这存在平台特定的影响。此行为是Qt 6.4新增的。
在Qt 6.4.1(MSVC2019,Windows 10)环境下,将QOpenGLWidget动态添加到继承自QWidget的MainWindow时,窗口会关闭后重新打开,不符合预期。
已找到临时解决方法,但不够优雅:
void MainWindow::showEvent( QShowEvent* event ) { Q_UNUSED( event ) QOpenGLWidget w; layout()->addWidget( &w ); layout()->removeWidget( &w ); }
提问:有没有更优雅的方法强制Qt默认使用OpenGL窗口类型?
补充说明:曾尝试在MainWindow::showEvent中调用windowHandle()->setSurfaceType(..),但后续创建QOpenGLWidget时会导致应用崩溃;由于MainWindow是QWidget,构造函数中无法使用windowHandle()(此时窗口对象尚未创建)。
方法一:构造函数中创建临时QOpenGLWidget子部件
在MainWindow的构造函数中,临时创建一个QOpenGLWidget作为子部件(无需添加到布局),Qt会自动将顶级窗口的表面类型切换为OpenGLSurface。临时部件销毁后,窗口类型不会回退,后续动态添加QOpenGLWidget时就不会触发窗口重建。
代码示例:
MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { // 临时创建QOpenGLWidget子部件,触发窗口表面类型切换 QOpenGLWidget tempGLWidget(this); // 出作用域后临时对象自动销毁,窗口保持OpenGLSurface类型 }
或使用动态分配方式(效果一致):
MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { QOpenGLWidget *tempGLWidget = new QOpenGLWidget(this); delete tempGLWidget; }
方法二:全局强制使用OpenGL表面(不推荐,影响所有窗口)
如果应用中所有窗口都需要使用OpenGL表面,可以在main()函数启动前设置全局属性:
#include <QApplication> int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_UseOpenGLES); // 或Qt::AA_UseDesktopOpenGL QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
注意:该方法会改变所有窗口的渲染方式,若仅单个窗口需要OpenGL表面,优先使用方法一。
内容的提问来源于stack exchange,提问作者Alexander Trotsenko

