0

The Qt documentation says:

When dynamically adding a QOpenGLWidget into a widget hierarchy, e.g. by parenting a new QOpenGLWidget to a widget where the corresponding top-level widget is already shown on screen, the associated native window may get implicitly destroyed and recreated if the QOpenGLWidget is the first of its kind within its window. This is because the window type changes from RasterSurface to OpenGLSurface and that has platform-specific implications. This behavior is new in Qt 6.4.

This is my case with Qt 6.4.1 (MSVC2019, Windows 10). When I dynamically add a new QOpenGLWidget to my window, the window closes and opens again. That is not good.

I found a workaround. Just add to the layout and then remove an empty QOpenGLWidget before the window is shown:

void MainWindow::showEvent( QShowEvent* event )
{
    Q_UNUSED( event )

    QOpenGLWidget w;
    layout()->addWidget( &w );
    layout()->removeWidget( &w );
}

But it seems like a dirty solution.. Does anyone know a more elegant way to force Qt to use the OpenGL window type by default?

UPD

The MainWindow class in the code above is derived from QWidget. I tried to call windowHandle()->setSurfaceType(..) in the MainWindow::showEvent. It leads to the app crash when I then create the QOpenGLWidget. Since MainWindow is QWidget, I can't use windowHandle() in the ctor because a window object is not created yet.

  • You're aware how long you `w` object lives? – chehrlic Apr 16 '23 at 08:19
  • Why you don't call QWindow::setSurfaceType? – Öö Tiib Apr 16 '23 at 08:28
  • @chehrlic, Yes, I know. The `w` object lives only in the method scope. That's why I remove it from the layout after adding. – Alexander Trotsenko Apr 16 '23 at 15:12
  • @ÖöTiib, Oh, I forgot this detail in my question.. The `MainWindow` class is derived from `QWidget`. I tried to call `windowHandle()->setSurfaceType(..)` in the `MainWindow::showEvent`. It leads to the app crash when I then create the `QOpenGLWidget`. Since `MainWindow` is `QWidget`, I can't call `windowHandle()` in the ctor because a window object is not created yet. – Alexander Trotsenko Apr 16 '23 at 15:21
  • The Qt kernel anyway generates the QWindow objects for your QWidgets. I actually do not know why you do not use QOpenGLWindow ... in my experience it performs better than widget. If you want you can embed QWindow in QWidget with QWidget::createWindowContainer(...) ... but like I say ... I do not know the whole reasoning. – Öö Tiib Apr 16 '23 at 20:09

1 Answers1

0

I suffered exactly the same problem...

The QT documentation seems to ONLY refer to manually creating QWindow and drawing directly to the Window. But in QWindow docs, say: https://doc.qt.io/qt-6/qwindow.html#details --> An application will typically use QWidget or QQuickView for its UI, and not QWindow directly. Still, it is possible to render directly to a QWindow with QBackingStore or QOpenGLContext, when wanting to keep dependencies to a minimum or when wanting to use OpenGL directly.

QMainWindow is poorly named, it is actually a QWidget. All QWidgets will internally create a QWindow when required (ie when top level widget is shown for the first time), but there seems to be no way to specify the Surface that should be requested from the new Window.

So instead I worked around the problem in a similar way to yourself. I had a QStackWidget that I was able to insert a (otherwise pointless) QOpenGLWidget.

stack->addWidget( new QOpenGLWidget() );

I didn't remove the widget after the first show like you did, as I knew I would never show that particular entry of the stack, and it would never draw anything. So it was there just to "vote" on the Surface required from the Window.

That worked, but had to label it with a big fat HACK comment, sigh.

elegant dice
  • 1,307
  • 12
  • 19