【问题标题】:Qt OpenGL Problems encountered upgrading from 5.10.0 to 5.12.1Qt OpenGL 从 5.10.0 升级到 5.12.1 遇到的问题
【发布时间】:2026-02-12 22:15:01
【问题描述】:

我有一个旧版 C++ Qt 应用程序,该应用程序已通过许多 Qt 版本进行了升级。我最近将它从 Qt 5.10.0 升级到 5.12.1,现在,突然之间,我的两个 OpenGL 显示器都遇到了问题,我不知道为什么。

问题的快速总结:

第一个显示绘制 3d 表面图。它非常旧(包含一个使用 glew 的旧控件)并且它使用现在已过时的 QGLWidget。我无法改变这一点。

class GLAdapterWidget : public QGLWidget
{
    // ...A whole lot of legacy code which has not changed...
public:
    // How I update the display

    void doUpdate()
    {
        someLegacyGLDrawingFunction();
        updateGL();  // fails if attribute Qt::WA_Mapped not set
    }
};

现在的问题是,一旦它被加载,它仍然显示为完全黑色,直到我真正在其边界内的某处单击鼠标。然后突然间它的 GL 绘图完美地出现了。这在 Qt 5.10.0 中没有发生。

调试我至少能够跟踪到小部件属性 Qt::WA_Mapped 。该属性未在我的小部件上设置,因此 Qt 在我单击它之前不会绘制它。一旦我在其边界内单击 Qt 设置该属性,它就可以正常工作。但是我尝试解决方法(例如调用 show() 或尝试在软件中设置该属性)没有效果。

第二个显示器更现代,使用 QOpenGLWidget。它显示了一个不断更新的实时摄像头图像。

class VideoDisplay : public QOpenGLWidget, 
                     protected QOpenGLFunctions_3_3_Core
{

    virtual void initializeGL() override
    {
        initializeOpenGLFunctions();
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-width()/2, width()/2, height()/2, -height()/2, -1, 1); 
        glClearColor(0.25f,0.25f,0.25f,1.0f);

    }
    virtual void paintGL() override
    {
        // Legacy Code that draws a live image using glDrawPixels and which has not changed.
    }
    virtual void resizeGL(int w, int h) override
    {
        glViewport(0,0,w,h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-w/2, w/2, h/2, -h/2, -1, 1);
    }
};

这个一开始似乎很好用。图像显示并更新。但是,如果我去显示一个较旧的 GLAdapterWidget 的实例,然后再回到这个显示 (VideoDisplay),它会突然显示为黑色,并且没有任何东西可以让它重绘。调试我看到paintGL仍在被调用并且它有一个有效的图像。所有参数看起来都不错。但什么都没有显示。

我意识到这不是很多事情要做。这段代码是如此古老和庞大,以至于我觉得发布大块代码并不会起到太大的作用,但会使事情变得混乱。

而且我意识到,在这两种情况下,罪魁祸首可能都是基于旧 QGLWidget 的显示器。但是当我说我不能放弃该代码时,我并不是在开玩笑,无论我多么想这样做

所以我(拼命地)关注这在 5.10.0 中有效而在 5.12.1 中无效的事实 我希望对 Qt 有更好了解的人可以识别任何特定的关键架构 Qt 在 5.10.0 和 5.12.1 之间发生了变化,这可能是为我提供调查途径或尝试变通方法的罪魁祸首

我需要创可贴。我不介意做这项工作,我只是不知道从哪里开始。

【问题讨论】:

  • 所以这就是你要做的:在你的存储库中创建一个 bug-reproducer 分支,切换到该分支,然后开始丢弃与问题无关的所有内容。您应该只剩下几百行散布在几个源和标题中,然后您将挤入一个以#include <QtOpenGL>(可能没有其他内容)开头的main.cpp,以#include "main.moc"结尾,并且适合 SO 格式 :)

标签: qt opengl qt5


【解决方案1】:

我在这里向 Qt 报告了这个问题:https://bugreports.qt.io/browse/QTBUG-72668 以及一个 hacky 解决方法,直到它得到解决。

解决方法:在设置为特定间隔的父 QMainWindow 上安装 QTimer。窗口暴露后且子 QOpenGLWidget isValid() 返回 true 后,将 widget 调整为不同大小(注意:不能相同大小,repaint()、update() 或 update(0, 0,宽度,高度)工作)

    QWindow *window = windowHandle();
    if(window && window->isExposed() && glWidget->isValid()) {
        resize(801,601);
        _timer.stop();
    }

【讨论】:

  • 我感觉其他人可能已经看到了这个。感谢您花时间写这篇文章
  • 是的,没问题,这个错误也影响了我们的工作。和你一样,我们也有很多依赖于 QGLWidget 的遗留代码。