C++ QGLWidget在Windows 7中显示为黑色

C++ QGLWidget在Windows 7中显示为黑色,c++,qt,opengl,qglwidget,C++,Qt,Opengl,Qglwidget,我使用Visual Studio 2010在Windows XP(Qt 4.7.2)中编写并测试了一些代码,然后在另一台安装了Windows 7的机器上进行了尝试 该程序打开一个QDialog并创建一个QGLWidget,我在其中显示网络摄像头图像(经过一些处理)。虽然在WindowsXP中图像显示正确,但当我在Windows7机器上测试程序时,QGLWidget变为黑色,没有显示图像。然而,奇怪的是,当我在窗口周围移动时,它离开了屏幕的边界,图像会显示一瞬间,当我再次停止移动时会变黑,这让我认

我使用Visual Studio 2010在Windows XP(Qt 4.7.2)中编写并测试了一些代码,然后在另一台安装了Windows 7的机器上进行了尝试

该程序打开一个QDialog并创建一个QGLWidget,我在其中显示网络摄像头图像(经过一些处理)。虽然在WindowsXP中图像显示正确,但当我在Windows7机器上测试程序时,QGLWidget变为黑色,没有显示图像。然而,奇怪的是,当我在窗口周围移动时,它离开了屏幕的边界,图像会显示一瞬间,当我再次停止移动时会变黑,这让我认为图像被正确接收/处理(有时),这可能是QTimer的问题

有关守则如下:

初始化:

void GLVideo::initializeGL()
{   
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    // Some OpenCV processing

    // Here I declare the timer, might it be the problem?
    m_timer = new QTimer(this);
    connect( m_timer, SIGNAL(timeout()), this, SLOT(timeOutSlot()) );
    m_timer->start( 33 );

}
每超时一次调用的插槽:

void GLVideo::timeOutSlot() 
{
    ReceiveInfo();
    LoadTextures();
}

void GLVideo::LoadTextures() 
{   
    // Get the image from the webcam
    ProcessCamera();

    glBindTexture(GL_TEXTURE_2D, texture);  
    glTexImage2D( GL_TEXTURE_2D, 0, 3, qImage->width(), 
        qImage->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, qImage->bits());
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    updateGL();
}

void GLVideo::resizeGL( int width, int height )
{
    height = height?height:1;
    glViewport( 0, 0, (GLint)width, (GLint)height );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
最后,小部件的绘制功能:

void GLVideo::paintGL()
{   
    glPushAttrib(GL_ALL_ATTRIB_BITS) ;
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    glPopAttrib() ;

    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glBindTexture(GL_TEXTURE_2D, texture);

    glColor4f(1.0f,1.0f,1.0f, 1.0f);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.65f, 1.24f, -3.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.65f, 1.24f, -3.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.65f,-1.24f, -3.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.65f,-1.24f, -3.0f);
    glEnd();    

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    // Some 2D drawing:
}

知道我做错了什么吗?可能是QTimer没有调用时隙超时吗?

您使用的OpenGL API不包括
paintGL()
resizeGL()
initializeGL()

调用插槽时,修改任何状态以绘制新帧,但不要调用OpenGL API。相反,调用
QWidget::updateGL()
,并在重新实现
paintGL()
时执行OpenGL调用

您遇到的问题是,在这三个函数之外,您的GL上下文不是当前的。在较旧的操作系统上,这可能不是问题,但任何具有合成窗口管理器的操作系统都会出现问题。例如,在您的情况下,您的程序可能是XP下唯一的OpenGL用户,因此您的程序始终是当前上下文。但在Windows7中,桌面本身使用的是相同的硬件,如果不是OpenGL,则是Direct3D

如果必须在这三个函数之外调用OpenGL函数,则需要首先调用
QGLWidget::makeCurrent()
,但请注意,这不是惯用用法


关于
initializeGL()
中的
QTimer
创建:在类的构造函数中创建计时器当然更为惯用,但在
initializeGL()
中也应该可以。

如果您的程序在Windows XP中工作,而不是在Windows 7中工作,我建议您检查是否有更新版本的显示驱动程序。

您好,我在使用新的NVIDIA驱动程序(280.something)+Win7时遇到了类似的问题(黑色屏幕,间歇性地正确绘制图像),我通过在paintGL结束时以及构造函数设置setAutoBufferSwap(true)中删除手动swapBuffers调用修复了这个问题。希望这能有所帮助。

Hi mmutz,您所提到的函数之外的OpenGL调用是正确的。我修改了代码(现在在paintGL()、resizeGL()和initializaGL()函数中只有OpenGL代码)。不过,我仍然有同样的问题。OpenGL小部件是黑色的,仅当我将窗口部分移动到屏幕限制之外时才会显示图像。为了确保,我有一个从paintGL调用的“绘制”函数。在该函数中,它调用所有其他OpenGL函数。这不应该是个问题,对吧?事实是,当图像“有时”显示时,我不认为这是司机的问题,但是。。。是的。更新到最新版本使程序在Windows 7中正常工作。谢谢我也有同样的问题。我的图形驱动程序是Nvidia GEforce 8400GS。如果我尝试从设备管理器更新它,我会收到一条消息,即驱动程序是最新的。我如何解决这个问题?我也有同样的问题。设备管理器说驱动程序已经更新,所以我尝试了上面的silvermaci解决方案。它不起作用,所以我下载了一个新的驱动程序安装程序,安装了它,然后它修复了这个问题。不要把设备管理器硬塞到这样的事情上。在供应商网站上检查驱动程序版本。