You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt4转Qt5:QGLWidget的renderPixmap()替代方案及空白图像问题

Qt4迁移Qt5后GLWidget渲染图像空白的解决方法

问题背景

在Qt4中基于QGLWidget实现的多边形细分渲染,调用renderPixmap()可正常生成图像,但迁移到Qt5后该方法返回空白图像。尝试切换到QOpenGLWidget、使用QOpenGLFrameBufferObject等方案均未解决问题。

关键修改点

  • 替换QGLWidget为QOpenGLWidget:Qt5中QGLWidget已被标记为过时,QOpenGLWidget对上下文管理和离屏渲染的支持更稳定。
  • 强制初始化Widget上下文:未显示的Widget无法完成OpenGL上下文初始化,需通过show()+hide()触发初始化流程,避免上下文创建失败。
  • 补充投影矩阵设置:原代码缺少正交/透视投影配置,导致多边形可能被渲染到视口外,需在resizeGL中设置适配坐标范围的投影矩阵。
  • 确保细分器正确输出OpenGL指令:确认MyTessellator的顶点回调函数正确调用glVertex系列接口,保证多边形绘制指令被执行。

修改后的完整代码

自定义OpenGL Widget类

#include <QOpenGLWidget>
#include <QOpenGLFramebufferObject>

class MyGLWidget : public QOpenGLWidget
{
    Q_OBJECT
public:
    MyGLWidget(const std::vector<BPolygon*> &polys, QWidget *parent = nullptr) 
        : QOpenGLWidget(parent), mPolys(polys) {}

    void paintGL() override;
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    QImage renderToImage(int w, int h);

private:
    std::vector<BPolygon *> mPolys;
};

核心渲染逻辑实现

void MyGLWidget::initializeGL()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glEnable(GL_CULL_FACE);
}

void MyGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // 根据你的多边形坐标范围调整投影参数,示例假设坐标在[-1,1]区间
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
}

void MyGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    MyTessellator tess;
    tess.boundary(false);
    tess.winding(GLU_TESS_WINDING_NONZERO);
    tess.beginPolygon();

    for(unsigned int i=0; i<mPolys.size(); i++)
    {
        tess.beginContour();
        for(BPoint* p = mPolys[i]->first; p;)
        {
            tess.vertex(IceVector3(p->x, p->y, 0.0));
            p = p->next;
            if(p == mPolys[i]->first) break;
        }
        tess.endContour();
    }

    tess.endPolygon();
}

QImage MyGLWidget::renderToImage(int w, int h)
{
    // 触发Widget初始化,隐藏窗口避免显示闪烁
    this->setFixedSize(w, h);
    this->show();
    this->hide();

    makeCurrent();

    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    QOpenGLFramebufferObject fbo(w, h, format);

    if (!fbo.isValid())
    {
        return QImage();
    }

    fbo.bind();
    resizeGL(w, h);
    paintGL();
    QImage result = fbo.toImage();
    fbo.release();

    doneCurrent();
    return result;
}

生成图像的调用代码

void MakeImage(const std::vector<BPolygon*>& polys, int w, int h)
{
    MyGLWidget mglWidget(polys);
    QImage image = mglWidget.renderToImage(w, h);
    image.save("output.png"); // 替换为你的保存路径
}

内容的提问来源于stack exchange,提问作者user20333483

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:35:26