QGLWidget выглядит черным в Windows 7 - PullRequest
4 голосов
/ 05 мая 2011

Я написал и протестировал некоторый код в Windows XP (Qt 4.7.2) с использованием Visual Studio 2010, а затем попробовал на другом компьютере с установленной 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();
}

И, наконец, функция рисованиявиджета:

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 не вызывает слот timeOutSlot?

Ответы [ 3 ]

5 голосов
/ 05 мая 2011

Вы используете API OpenGL за пределами paintGL(), resizeGL() или initializeGL().

Когда вызывается ваш слот, измените любое состояние, чтобы можно было рисовать новый кадр, но пока не вызывайте OpenGL API .Вместо этого вызовите QWidget::updateGL() и выполните вызовы OpenGL при повторной реализации paintGL().

Проблема, с которой вы сталкиваетесь, заключается в том, что вне этих трех функций ваш контекст GL не является текущим.На старых ОС это может не быть проблемой, но любая ОС с композитным оконным менеджером создаст проблемы.Например, в вашем случае ваша программа, возможно, была единственным пользователем OpenGL под XP, поэтому у вас всегда был текущий контекст.Но в Windows 7 сам рабочий стол использует, если не OpenGL, то Direct3D, т.е.то же самое оборудование.

Если вы абсолютно должны вызвать функцию OpenGL вне этих трех функций, вам сначала нужно вызвать QGLWidget::makeCurrent(), но учтите, что это не идиоматическое использование.

Относительно создания QTimer в initializeGL(): безусловно, более идиоматично создавать этот таймер в конструкторе класса, но в initializeGL() тоже должно быть хорошо.

3 голосов
/ 30 августа 2011

Привет, у меня была похожая проблема (черный экран с периодически правильно нарисованным изображением) с новыми драйверами NVIDIA (280.something) + Win7, я исправил проблему, удалив ручной вызов swapBuffers в конце моего paintGL и в конструкторе настройка setAutoBufferSwap (true) - надеюсь, это поможет.

3 голосов
/ 05 мая 2011

Если ваша программа работает в Windows XP, но не в Windows 7, я рекомендую вам проверить, есть ли более новая версия драйвера дисплея.

...