单击按钮后如何在OpenGLWindow或OpenGLWidget中重新绘制或渲染某些内容?

时间:2019-05-24 09:36:44

标签: python opengl pyqt pyqt5

我正在开发一个软件,我想在该软件中添加一个 OpenGL可视化窗口,以便当用户按下某些按钮(例如单击以渲染Triangle)时可以在此窗口中渲染某些东西应该绘制一个三角形,或者当他单击球体时,应该绘制一个球体。

实际上我想将opengl东西渲染为搅拌器的整体性等。

我正在 PyQt5 中完成所有这些操作。任何人都可以建议我或为我提供完善的建议。

我看过Qt官方文档,但是它们都很混乱。

我认为所有这些都可以使用 QWindow,QPainter,QOpenGLWindow 完成,但是我无法实现,任何人都可以为我提供代码吗?

这是可以正常工作的代码,但不允许在按下的按钮上绘制内容。

class Ui_MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        .
        .
        .
        self.openGLWidget = OGLWidget(self.main)
        self.openGLWidget.setObjectName("openGLWidget")
        self.verticalLayout.addWidget(self.openGLWidget)
        .
        .
        .
        self.show()

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("self", "self"))
        self.pushButton.setText(_translate("self", "PushButton"))

    def keyPressEvent(self, e):
        print(e.key())




class OGLWidget(QtWidgets.QOpenGLWidget):
    def initializeGL(self):
        glClearColor(0.2,0.2,0.2,0)

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        .
        .
        .

    def resizeGL(self,w,h):
        .
        .
        .

if __name__ == "__main__":
        .
        .
        .

这是我使用QWindow和QOpenGLWindow的代码,但是它不起作用

class Ui_MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        .
        .
        .
        self.openGLWidget = ChocoWindow(self.main)
        self.openGLWidget.setObjectName("openGLWidget")
        .
        .
        .
        self.show()

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("self", "self"))
        self.pushButton.setText(_translate("self", "PushButton"))

    def keyPressEvent(self, e):
        print(e.key())


class OpenGLWindow(QtGui.QWindow):
    def __init__(self, parent=None):
        super(OpenGLWindow, self).__init__(parent)

        self.m_update_pending = False
        self.m_animating = False
        self.m_context = None
        self.m_gl = None

        self.setSurfaceType(QtGui.QWindow.OpenGLSurface)

    def initialize(self):
        pass

    def setAnimating(self, animating):
        self.m_animating = animating

        if animating:
            self.renderLater()

    def renderLater(self):
        if not self.m_update_pending:
            self.m_update_pending = True
            QtGui.QGuiApplication.postEvent(self, QtCore.QEvent(QtCore.QEvent.UpdateRequest))

    def renderNow(self):
        if not self.isExposed():
            return

        self.m_update_pending = False

        needsInitialize = False

        if self.m_context is None:
            self.m_context = QtGui.QOpenGLContext(self)
            self.m_context.setFormat(self.requestedFormat())
            self.m_context.create()

            needsInitialize = True

        self.m_context.makeCurrent(self)

        if needsInitialize:
            version = QtGui.QOpenGLVersionProfile()
            version.setVersion(2, 0)
            self.m_gl = self.m_context.versionFunctions(version)
            self.m_gl.initializeOpenGLFunctions()

            self.initialize(self.m_gl)

        self.render(self.m_gl)

        self.m_context.swapBuffers(self)

        if self.m_animating:
            self.renderLater()

    def event(self, event):
        print(event)
        print(event.type())
        if event.type() == QtCore.QEvent.UpdateRequest:
            self.renderNow()
            return True

        return super(OpenGLWindow, self).event(event)

    def exposeEvent(self, event):
        self.renderNow()

    def resizeEvent(self, event):
        self.renderNow()

def triangle(self):
    glBegin(GL_TRIANGLES)
    glColor3f(1.0, 0.0, 0.0)
    glVertex3f(-0.5, -0.5, 0)
    glColor3f(0.0, 1.0, 0.0)
    glVertex3f( 0.5, -0.5, 0)
    glColor3f(0.0, 0.0, 1.0)
    glVertex3f( 0.0,  0.5, 0)
    glEnd()
    glViewport(0, 0, self.width(), self.height())
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, 1, 1, 100.0)
    gluLookAt(0,0,5,0,0,0,0,1,0)

class ChocoWindow(OpenGLWindow):

    def __init__(self, parent=None):
        super(ChocoWindow, self).__init__(parent)

    def initialize(self, gl):
        glClearColor(0.2,0.2,0.2,0)
    def render(self, gl):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        triangle(self)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window  = Ui_MainWindow()
    sys.exit(app.exec_())

这不起作用,这表明出现以下错误

Traceback (most recent call last):
  File "code.py", line 181, in <module>
    window  = Ui_MainWindow()
  File "code.py", line 29, in __init__
    self.openGLWidget = ChocoWindow(self.main)
  File "code.py", line 150, in __init__
    super(ChocoWindow, self).__init__(parent)
  File "code.py", line 62, in __init__
    super(OpenGLWindow, self).__init__(parent)
TypeError: arguments did not match any overloaded call:
  QWindow(screen: QScreen = None): argument 1 has unexpected type 'QWidget'
  QWindow(QWindow): argument 1 has unexpected type 'QWidget'

我想将opengl东西呈现为搅拌器的整体性等。

1 个答案:

答案 0 :(得分:0)

QWidget仅允许其他QWidget作为子对象,因此针对您的情况的解决方案是使用方法QWidget::createWindowContainer()将QWindow转换为QWidget:

from PyQt5 import QtCore, QtGui, QtWidgets
from OpenGL import GL, GLU


class OpenGLWindow(QtGui.QWindow):
    def __init__(self, parent=None):
        super(OpenGLWindow, self).__init__(parent)

        self.m_update_pending = False
        self.m_animating = False
        self.m_context = None
        self.m_gl = None

        self.setSurfaceType(QtGui.QWindow.OpenGLSurface)

    def initialize(self):
        pass

    def setAnimating(self, animating):
        self.m_animating = animating

        if animating:
            self.renderLater()

    def renderLater(self):
        if not self.m_update_pending:
            self.m_update_pending = True
            QtGui.QGuiApplication.postEvent(
                self, QtCore.QEvent(QtCore.QEvent.UpdateRequest)
            )

    def renderNow(self):
        if not self.isExposed():
            return

        self.m_update_pending = False

        needsInitialize = False

        if self.m_context is None:
            self.m_context = QtGui.QOpenGLContext(self)
            self.m_context.setFormat(self.requestedFormat())
            self.m_context.create()

            needsInitialize = True

        self.m_context.makeCurrent(self)

        if needsInitialize:
            version = QtGui.QOpenGLVersionProfile()
            version.setVersion(2, 0)
            self.m_gl = self.m_context.versionFunctions(version)
            self.m_gl.initializeOpenGLFunctions()

            self.initialize(self.m_gl)

        self.render(self.m_gl)

        self.m_context.swapBuffers(self)

        if self.m_animating:
            self.renderLater()

    def event(self, event):
        if event.type() == QtCore.QEvent.UpdateRequest:
            self.renderNow()
            return True
        return super(OpenGLWindow, self).event(event)

    def exposeEvent(self, event):
        self.renderNow()

    def resizeEvent(self, event):
        self.renderNow()


def triangle(self):
    GL.glBegin(GL.GL_TRIANGLES)
    GL.glColor3f(1.0, 0.0, 0.0)
    GL.glVertex3f(-0.5, -0.5, 0)
    GL.glColor3f(0.0, 1.0, 0.0)
    GL.glVertex3f(0.5, -0.5, 0)
    GL.glColor3f(0.0, 0.0, 1.0)
    GL.glVertex3f(0.0, 0.5, 0)
    GL.glEnd()
    GL.glViewport(0, 0, self.width(), self.height())
    GL.glMatrixMode(GL.GL_PROJECTION)
    GL.glLoadIdentity()
    GLU.gluPerspective(45, 1, 1, 100.0)
    GLU.gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0)


class ChocoWindow(OpenGLWindow):
    def initialize(self, gl):
        GL.glClearColor(0.2, 0.2, 0.2, 0)

    def render(self, gl):
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
        triangle(self)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        label = QtWidgets.QLabel("ChocoWindow", alignment=QtCore.Qt.AlignCenter)
        label.setSizePolicy(
            QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum
        )
        window = ChocoWindow()
        widget = QtWidgets.QWidget.createWindowContainer(window)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(label)
        lay.addWidget(widget)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

enter image description here