我使用Visual Studio 2010在Windows XP(Qt 4.7.2)中编写并测试了一些代码,然后我尝试安装了Windows 7的另一台机器。
该程序打开一个QDialog并创建一个QGLWidget,我在其中显示网络摄像头图像(进行一些处理)。在Windows XP中,图像显示正确,在我在Windows 7计算机上测试程序时,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();
}
最后,Widget的绘制功能:
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没有调用SLOT timeOutSlot吗?
答案 0 :(得分:5)
您在paintGL()
,resizeGL()
或initializeGL()
之外使用OpenGL API。
调用插槽时,修改任何状态以便能够绘制新帧但不要调用OpenGL API 。相反,请调用QWidget::updateGL()
,并在重新实现paintGL()
时执行OpenGL调用。
您遇到的问题是,在这三个函数之外,您的GL上下文不是当前的上下文。在较旧的操作系统上,这可能不是问题,但任何具有合成窗口管理器的操作系统都会出现问题。例如,在您的情况下,您的程序可能是XP下唯一的OpenGL用户,因此您的程序始终是当前上下文。但是在Windows 7中,如果不是OpenGL,桌面本身就使用Direct3D,即。相同的硬件。
如果你绝对必须在这三个函数之外调用OpenGL函数,你需要先调用QGLWidget::makeCurrent()
,但请注意这不是惯用的。
关于QTimer
中的initializeGL()
创建:在类的构造函数中创建该计时器肯定更为惯用,但在initializeGL()
中也应该没问题。
答案 1 :(得分:3)
如果您的程序在Windows XP中运行但在Windows 7中运行,我建议您检查是否有更新版本的显示驱动程序。
答案 2 :(得分:3)
嗨我有一个类似的问题(黑屏与间歇正确绘制的图像)与新的NVIDIA驱动程序(280.something)+ Win7,我通过删除我的paintGL末尾和构造函数中的手动swapBuffers调用修复了问题设置setAutoBufferSwap(true) - 希望这有帮助。