Search code examples
glfwpyside2pyopengl

PySide2 How to add existing OpenGL window into QGLWidget


I've currently have written a simple window class using glfw and pyopengl. Now, I would like to use it with qt widgets.

I've discovered that QGLWidget provides 3 functions to reimplement: paintGL, resizeGL, initializeGL. Unfortunately things like context creation and all the drawing was created using glfw and pyopengl.

So, is it possible to use it with QGLWidget somehow?

Here's a window code:

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")

Solution

  • Ok, it seems that I shouldn't use QGLWidget, which is a bit outdated. Instead I'll use 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")
    

    Also to setup OpenGL version and other things, which I normally do with GLFW, I re-implement a QSurfaceFormat class with the settings I need.

    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)
    

    After, initialize surface before OpenGLWidget in main loop