QGLWidget 在 Windows 7 中显示为黑色
我使用 Visual Studio 2010 在 Windows XP (Qt 4.7.2) 中编写并测试了一些代码,然后在另一台安装了 Windows 7 的计算机上进行了尝试。
该程序打开一个 QDialog 并创建一个 QGLWidget,我在其中显示网络摄像头图像(经过一些处理)。虽然在 Windows XP 中图像显示正确,但当我在 Windows 7 机器上测试该程序时,QGLWidget 变黑并且没有图像显示。但奇怪的是,当我在窗口周围移动并且它超出屏幕边界时,图像会立即显示,当我再次停止移动时图像会变成一片漆黑,这让我认为图像已正确接收/processed(有时),这可能是 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 没有调用 SLOT timeOutSlot 吗?
I wrote and tested some code in a Windows XP (Qt 4.7.2) using Visual Studio 2010 and then I tried on another machine with Windows 7 installed.
The program opens a QDialog and creates a QGLWidget where I show webcam images (with some processing). While in Windows XP the images are shown correctly, at the moment that I test the program in a Windows 7 machine, the QGLWidget turns black and no image is shown. It is strange, though, that when I move around the window and it gets out of the borders of the screen, the image is shown for an instant and pitch black when I stop moving again, which makes me think that the images are correctly received/processed (some times), and that it might be a problem with a QTimer.
The relevant code is:
Initialization:
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 );
}
Slot that is called every timeout:
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();
}
And finally, the paint function of the 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:
}
Any idea on what am I doing wrong? Might it be the QTimer that is not calling the SLOT timeOutSlot?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您在
paintGL()
、resizeGL()
或initializeGL()
之外使用 OpenGL API。当您的槽被调用时,修改任何状态以便能够绘制新帧,但暂时不要调用 OpenGL API。相反,请调用
QWidget::updateGL()
,并在重新实现paintGL()
中执行 OpenGL 调用。您遇到的问题是,除了这三个函数之外,您的 GL 上下文不是当前的。在较旧的操作系统上,这可能不是问题,但任何具有合成窗口管理器的操作系统都会出现问题。例如,在您的情况下,您的程序可能是 XP 下唯一的 OpenGL 用户,因此您的程序始终是当前上下文。但在Windows 7中,桌面本身使用的不是OpenGL,而是Direct3D,即。相同的硬件。
如果您绝对必须在这三个函数之外调用OpenGL函数,则需要首先调用
QGLWidget::makeCurrent()
,但请注意,这不是惯用用法。关于在
initializeGL()
中创建 QTimer:在类的构造函数中创建该计时器当然更惯用,但在initializeGL()< 中应该没问题。 /代码>,也是。
You're using OpenGL API outside of
paintGL()
,resizeGL()
, orinitializeGL()
.When your slot is called, modify any state to be able to draw the new frame, but don't call OpenGL API yet. Instead, call
QWidget::updateGL()
, and do the OpenGL calls in your reimplementation ofpaintGL()
.The problem you're experiencing is that, outside these three functions, your GL context isn't the current one. On older OSs, that might not be a problem, but any OS with a compositing window manager will make problems. E.g., in your case, your program may have been the only OpenGL user under XP, so yours was always the current context. But in Windows 7, the desktop itself uses, if not OpenGL, then Direct3D, ie. the same hardware.
If you absolutely must call OpenGL function outside those three functions, you need to call
QGLWidget::makeCurrent()
first, but note that this is not idiomatic use.Regarding the
QTimer
creation ininitializeGL()
: it's certainly more idiomatic to create that timer in the class' constructor, but it should be ok ininitializeGL()
, too.如果您的程序可以在Windows XP中运行,但不能在Windows 7中运行,我建议您检查是否有更新版本的显示驱动程序。
If your program works in Windows XP but not in Windows 7, I recommend that you should check if there is a newer version of the display driver.
您好,我在使用新的 NVIDIA 驱动程序 (280.something) + Win7 时遇到了类似的问题(黑屏,间歇性地正确绘制图像),我通过删除 PaintGL 末尾的手动 swapBuffers 调用和构造函数设置 setAutoBufferSwap(正确) - 希望这有帮助。
Hi I had a similar problem (black screen with intermittently correctly drawn image) with new NVIDIA drivers (280.something) + Win7, I fixed the problem by removing the manual swapBuffers call at the end of my paintGL and in the constructor setting setAutoBufferSwap(true) - hope this helps.