Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Drawing a triangle using PyQt5 and OpenGL 3.3 (rewriting the Qt C++ example)



  • My current PyQt5 example does not show a window and does not give me any error messages.

    This is Qt C++ example that works very good. I want to use QOpenGLBuffer in my PyQt5 code.

    main.cpp

    #include <QApplication>
    #include <QOpenGLWidget>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLBuffer>
    
    class Widget : public QOpenGLWidget {
        Q_OBJECT
    public:
        Widget(QWidget *parent = nullptr) : QOpenGLWidget(parent) { }
    private:
        QOpenGLShaderProgram m_program;
        QOpenGLBuffer m_vertPosBuffer;
    
        void initializeGL() override {
            glClearColor(0.5f, 0.8f, 0.7f, 1.f);
            resize(400, 500);
            const char *vertShaderSrc =
                    "attribute vec3 aPosition;"
                    "void main()"
                    "{"
                    "    gl_Position = vec4(aPosition, 1.0);"
                    "}";
            const char *fragShaderSrc =
                    "void main()"
                    "{"
                    "    gl_FragColor = vec4(0.5, 0.2, 0.9, 1.0);"
                    "}";
            m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertShaderSrc);
            m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShaderSrc);
            m_program.link();
            m_program.bind();
            float vertPositions[] = {
                -0.5f, -0.5f, 0.f,
                0.5f, -0.5f, 0.f,
                0.f, 0.5f, 0.f
            };
            m_vertPosBuffer.create();
            m_vertPosBuffer.bind();
            m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
            m_program.bindAttributeLocation("aPosition", 0);
            m_program.setAttributeBuffer(0, GL_FLOAT, 0, 3);
            m_program.enableAttributeArray(0);
        }
        void paintGL() override {
            glClear(GL_COLOR_BUFFER_BIT);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }
        void resizeGL(int w, int h) override {
            glViewport(0, 0, w, h);
        }
    };
    
    #include "main.moc"
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        Widget w;
        w.show();
        return a.exec();
    }
    

    This is my trying to rewrite the code above to PyQt5. As you can see I want to rewrite it very close to Qt C++. I want to have two very similar example. But this code does not show a windows and does not show any error messages.

    main.py

    import sys
    import numpy as np
    from OpenGL import GL as gl
    from PyQt5.QtWidgets import QOpenGLWidget, QApplication
    from PyQt5.QtGui import (QOpenGLBuffer, QOpenGLShaderProgram,
        QOpenGLShader)
    from PyQt5.QtCore import Qt
    
    class OpenGLWidget(QOpenGLWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("Triangle, PyQt5, OpenGL ES 2.0")
            self.resize(300, 300)
        def initializeGL(self):
            gl.glClearColor(0.5, 0.8, 0.7, 1.0)
            vertShaderSrc = """
                attribute vec3 aPosition;
                void main()
                {
                    gl_Position = vec4(aPosition, 1.0);
                }
            """
            fragShaderSrc = """
                void main()
                {
                    gl_FragColor = vec4(0.5, 0.2, 0.9, 1.0);
                }
            """
            program = QOpenGLShaderProgram()
            program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertShaderSrc)
            program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragShaderSrc)
            program.link()
            program.bind()
            vertPositions = np.array([
                -0.5, -0.5, 0.0,
                0.5, -0.5, 0.0,
                0.0, 0.5, 0.0], dtype=np.float32)
            vertPosBuffer = QOpenGLBuffer()
            vertPosBuffer.create()
            vertPosBuffer.bind()
            vertPosBuffer.allocate(vertPositions, len(vertPositions) * 4)
            program.bindAttributeLocation("aPosition", 0)
            program.setAttributeBuffer(0, gl.GL_FLOAT, 0, 3)
            program.enableAttributeArray(0)
    
        def paintGL(self):
            gl.glClear(gl.GL_COLOR_BUFFER_BIT)
            gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)
    
    def main():
        QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
        a = QApplication(sys.argv)
        w = OpenGLWidget()
        w.show()
        sys.exit(a.exec_())
    
    if __name__ == "__main__":
        main()
    


  • eyllanesc solved my problem here: https://stackoverflow.com/questions/64914388/drawing-a-triangle-using-pyqt5-and-opengl-rewriting-the-qt-c-example/64915511#64915511

    The problem is that the QOpenGLBuffer is a local variable that is destroyed instantly, whereas in C++ QOpenGLBuffer is an attribute of the class. The solution is to change vertPosBuffer to self.vertPosBuffer



  • eyllanesc solved my problem here: https://stackoverflow.com/questions/64914388/drawing-a-triangle-using-pyqt5-and-opengl-rewriting-the-qt-c-example/64915511#64915511

    The problem is that the QOpenGLBuffer is a local variable that is destroyed instantly, whereas in C++ QOpenGLBuffer is an attribute of the class. The solution is to change vertPosBuffer to self.vertPosBuffer


Log in to reply