使用 PyQt5 和 OpenGL 绘制三角形(重写 Qt C++ 示例)

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

我当前的 PyQt5 示例没有显示 window 并且没有给我任何错误消息。

这是运行良好的 Qt C++ 示例。我想在我的 PyQt5 代码中使用 QOpenGLBuffer。

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();
}

这是我尝试将上面的代码重写为 PyQt5。如您所见,我想将其重写为非常接近 Qt C++。我想要两个非常相似的例子。但是此代码不显示 windows 并且不显示任何错误消息。

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

问题在于 QOpenGLBuffer 是一个立即销毁的局部变量,而在 C++ 中 QOpenGLBuffer 是 class 的一个属性。解决办法是把vertPosBuffer改成self.vertPosBuffer