此問題可能與another SO question有關。PyQT5 OpenGL 4.1核心配置文件 - 無效的幀緩衝區操作 - Mac OS
我正在運行MacOS 10.11.2 El Capitan。希望豐富的GUI功能 圍繞我的OpenGL應用程序我決定給PyQT5一個創建OpenGL上下文的 ,這樣我就可以將我的OpenGL作爲一個QtWidget int整合到一個GUI應用程序中。
QT5提供QGlWidget幾個API方法,我很快在這裏總結一下:
- :以前
paintGL
paintGL
被調用一次:地方畫的東西主動幀緩衝
我能夠創建小部件和初始化着色器等。但當談到幀緩衝相關操作,如glClear
出現的錯誤:
File "errorchecker.pyx", line 53, in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckError (src/errorchecker.c:1218)
OpenGL.error.GLError: GLError(
err = 1286,
description = 'invalid framebuffer operation',
baseOperation = glClear,
cArguments = (GL_COLOR_BUFFER_BIT,)
)
我發現了一個website有關相關問題的報告。看起來,調用API方法時沒有配置幀緩衝區。因爲我覺得應該是QT的任務我沒有嘗試自己配置窗口幀緩衝區。但是我發現,在API方法的一些調用之後,幀緩衝是神奇地創建的。因此,我建立一個小黑客,等到paintGL
被調用NSKIP_PAINTGL=3
次。然後我配置我的對象,以便正常的paintGL進程開始工作。這似乎工作。但有時它需要超過NSKIP_PAINTGL
次,所以我在解決方法中包含了一些sleep
。 QT似乎應該在創建幀緩衝區之後。也許QT在一個單獨的線程中執行它?該QOpenGLWidget確認幀緩衝器可能不能在一段時間內被創建:
返回幀緩衝器對象句柄或0,如果尚未初始化。
我不喜歡這樣的工作,因爲我害怕這裏提出的條件。此外,我在這裏沒有很多控制權(我需要依靠QT首先調用paintGL的事實,以便黑客可以工作)。我不熟悉的那一刻QT框架,以便這裏是我的問題:
如何創建,當創建QGLControllerWidget
一些還挺循環,運行由一個try/catch
覆蓋updateGL
方法和長重試的GlError
出現?或者,循環可以監聽QOpenGLWidget::defaultFramebufferObject()
並等待對象句柄。
當然我想把這個黑客儘可能優雅地整合到QT應用程序流程中 - 這樣做可愛的方式。
還是我錯過了這裏的東西?是否有可能以某種方式設置PyQT,以便在有效的幀緩衝區存在之前它不會調用OpenGL API方法?
這裏是一個孤立的代碼破解它運行在我的Mac:
from PyQt5 import QtGui, QtCore, QtOpenGL, QtWidgets
from PyQt5.QtOpenGL import QGLWidget
from OpenGL.GL import *
from time import sleep
NSKIP_PAINTGL = 3
class QGLControllerWidget(QGLWidget):
"""
basic test widget: a black screen which clears
framebuffer on paintGL event so it should stay
black on resize and so on.
"""
def __init__(self, format = None):
super(QGLControllerWidget, self).__init__(format, None)
self._weird_pyqt5_framebuffer_hack = 0
# replace paintGL by workaround
self._weird_pyqt5_framebuffer_hack_original_paintGL = self.paintGL
self.paintGL = self._weird_pyqt5_framebuffer_hack_paintGL
def initializeGL(self):
pass
def _weird_pyqt5_framebuffer_hack_paintGL(self):
self._weird_pyqt5_framebuffer_hack += 1
if self._weird_pyqt5_framebuffer_hack < NSKIP_PAINTGL:
return
sleep(0.1)
# restore original paintGL
self.paintGL = self._weird_pyqt5_framebuffer_hack_original_paintGL
self.updateGL()
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT)
if __name__ == '__main__':
import sys
class QTWithGLTest(QtWidgets.QMainWindow):
def __init__(self, parent = None):
super(QTWithGLTest, self).__init__(parent)
# MacOS core profile 4.1
qgl_format = QtOpenGL.QGLFormat()
qgl_format.setVersion(4, 1)
qgl_format.setProfile(QtOpenGL.QGLFormat.CoreProfile)
qgl_format.setSampleBuffers(True)
self.widget = QGLControllerWidget(qgl_format)
self.setCentralWidget(self.widget)
self.show()
app = QtWidgets.QApplication(sys.argv)
window = QTWithGLTest()
window.show()
app.exec_()
注意,同樣的C++代碼片段,歡迎我會嘗試轉換然後進入蟒蛇。
呃......我不確定這個問題到底是什麼。你可以做一個C++測試用例嗎? – peppe
我不熟悉C++。基本上問題是,在調用導致錯誤的paintGL()方法之前,QT不會初始化幀緩衝區。我將不勝感激一些提示如何實現一種控制機制,它允許我在第一次調用paintGL之前等待/強制幀緩衝區被初始化。啊哈! – keksnicoh