PySide2 如何将现有的 OpenGL window 添加到 QGLWidget
PySide2 How to add existing OpenGL window into QGLWidget
我目前已经使用 glfw 和 pyopengl 编写了一个简单的 window class。现在,我想将它与 qt widgets 一起使用。
我发现 QGLWidget 提供了 3 个函数来重新实现:paintGL, resizeGL, initializeGL
。不幸的是,上下文创建和所有绘图都是使用 glfw 和 pyopengl 创建的。
那么,是否可以通过某种方式将它与 QGLWidget 一起使用?
这是一个 window 代码:
class Viewport(object):
def __init__(self, widht, height, title="OpenGL Window", r=0.2, g=0.3, b=0.3, a=1.0):
super().__init__()
self.widht = widht
self.height = height
self.window_title = title
self.background_color = (r, g, b, a)
self.__check_glfw()
self.window = self.__create_window()
def main_loop(self):
while not glfw.window_should_close(self.window):
self.processEvents(self.window)
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
# DO STUFF HERE
#--------------
glfw.swap_buffers(self.window)
glfw.poll_events()
glfw.terminate()
def processEvents(self, window):
if glfw.get_key(window, glfw.KEY_ESCAPE) is glfw.PRESS:
glfw.set_window_should_close(window, True)
def __create_window(self):
window = glfw.create_window(self.widht, self.height, self.window_title, None, None)
# check if window was created
if not window:
glfw.terminate()
dialog = ExceptionDialog("GLWFError::Cannot initialize window")
glfw.set_window_pos(window, 400, 200)
glfw.make_context_current(window)
return window
def __check_glfw(self):
# Initiallize gflw
if not glfw.init():
dialog = ExceptionDialog("GLFWError::The GLFW lib cannot initialized")
好吧,看来我不应该使用QGLWidget,它有点过时了。
相反,我将使用 QOpenGLWidget:
class nViewport(QtWidgets.QOpenGLWidget):
def __init__(self, width, height, title="Qt OpenGl Window", r=0.2, g=0.3, b=0.3, a=1.0):
super().__init__()
self.widht = width
self.height = height
self.bg_color = (r, g, b, a)
self.setWindowTitle(title)
self.resize(self.widht, self.height)
def initializeGL(self):
pass
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glClearColor(self.bg_color[0], self.bg_color[1],
self.bg_color[2], self.bg_color[3])
def resizeGL(self, w:int, h:int):
glViewport(0, 0, w, h)
def keyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key_Escape:
app.exit()
event.accept()
def printDebugInfo(self):
print(f"QT_OPENGL_WIDGET::{self.__class__.__name__}")
print("------------------------------>")
print(f"INFO::GL_VERSION::{glGetString(GL_VERSION)}")
print("------------------------------>\n")
还要设置 OpenGL 版本和其他我通常用 GLFW 做的事情,我重新实现了一个 QSurfaceFormat class 使用我需要的设置。
class GLSurfaceFormat(QtGui.QSurfaceFormat):
def __init__(self, major: int = 4, minor: int = 3,
profile: QtGui.QSurfaceFormat.OpenGLContextProfile = QtGui.QSurfaceFormat.CoreProfile,
color_space: QtGui.QSurfaceFormat.ColorSpace = QtGui.QSurfaceFormat.sRGBColorSpace):
super().__init__()
self.gl_major = major
self.gl_minor = minor
self.gl_profile = profile
self.color_space = color_space
self.__initSurface()
def __initSurface(self):
self.setRenderableType(QtGui.QSurfaceFormat.OpenGL)
self.setMajorVersion(self.gl_major)
self.setMinorVersion(self.gl_minor)
self.setProfile(self.gl_profile)
self.setColorSpace(self.color_space)
# You can change it to TripleBuffer if your platform supports it
self.setSwapBehavior(QtGui.QSurfaceFormat.DoubleBuffer)
之后,在主循环中的 OpenGLWidget 之前初始化表面
我目前已经使用 glfw 和 pyopengl 编写了一个简单的 window class。现在,我想将它与 qt widgets 一起使用。
我发现 QGLWidget 提供了 3 个函数来重新实现:paintGL, resizeGL, initializeGL
。不幸的是,上下文创建和所有绘图都是使用 glfw 和 pyopengl 创建的。
那么,是否可以通过某种方式将它与 QGLWidget 一起使用?
这是一个 window 代码:
class Viewport(object):
def __init__(self, widht, height, title="OpenGL Window", r=0.2, g=0.3, b=0.3, a=1.0):
super().__init__()
self.widht = widht
self.height = height
self.window_title = title
self.background_color = (r, g, b, a)
self.__check_glfw()
self.window = self.__create_window()
def main_loop(self):
while not glfw.window_should_close(self.window):
self.processEvents(self.window)
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
# DO STUFF HERE
#--------------
glfw.swap_buffers(self.window)
glfw.poll_events()
glfw.terminate()
def processEvents(self, window):
if glfw.get_key(window, glfw.KEY_ESCAPE) is glfw.PRESS:
glfw.set_window_should_close(window, True)
def __create_window(self):
window = glfw.create_window(self.widht, self.height, self.window_title, None, None)
# check if window was created
if not window:
glfw.terminate()
dialog = ExceptionDialog("GLWFError::Cannot initialize window")
glfw.set_window_pos(window, 400, 200)
glfw.make_context_current(window)
return window
def __check_glfw(self):
# Initiallize gflw
if not glfw.init():
dialog = ExceptionDialog("GLFWError::The GLFW lib cannot initialized")
好吧,看来我不应该使用QGLWidget,它有点过时了。 相反,我将使用 QOpenGLWidget:
class nViewport(QtWidgets.QOpenGLWidget):
def __init__(self, width, height, title="Qt OpenGl Window", r=0.2, g=0.3, b=0.3, a=1.0):
super().__init__()
self.widht = width
self.height = height
self.bg_color = (r, g, b, a)
self.setWindowTitle(title)
self.resize(self.widht, self.height)
def initializeGL(self):
pass
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glClearColor(self.bg_color[0], self.bg_color[1],
self.bg_color[2], self.bg_color[3])
def resizeGL(self, w:int, h:int):
glViewport(0, 0, w, h)
def keyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key_Escape:
app.exit()
event.accept()
def printDebugInfo(self):
print(f"QT_OPENGL_WIDGET::{self.__class__.__name__}")
print("------------------------------>")
print(f"INFO::GL_VERSION::{glGetString(GL_VERSION)}")
print("------------------------------>\n")
还要设置 OpenGL 版本和其他我通常用 GLFW 做的事情,我重新实现了一个 QSurfaceFormat class 使用我需要的设置。
class GLSurfaceFormat(QtGui.QSurfaceFormat):
def __init__(self, major: int = 4, minor: int = 3,
profile: QtGui.QSurfaceFormat.OpenGLContextProfile = QtGui.QSurfaceFormat.CoreProfile,
color_space: QtGui.QSurfaceFormat.ColorSpace = QtGui.QSurfaceFormat.sRGBColorSpace):
super().__init__()
self.gl_major = major
self.gl_minor = minor
self.gl_profile = profile
self.color_space = color_space
self.__initSurface()
def __initSurface(self):
self.setRenderableType(QtGui.QSurfaceFormat.OpenGL)
self.setMajorVersion(self.gl_major)
self.setMinorVersion(self.gl_minor)
self.setProfile(self.gl_profile)
self.setColorSpace(self.color_space)
# You can change it to TripleBuffer if your platform supports it
self.setSwapBehavior(QtGui.QSurfaceFormat.DoubleBuffer)
之后,在主循环中的 OpenGLWidget 之前初始化表面