如何在PyQt6应用程序中使用QOpenGLWidget

问题描述 投票:0回答:1

我的 PyQt6 程序引发此错误。

Traceback (most recent call last):
  File "C:\Users\user\AppData\Roaming\Python\Python311\site-packages\OpenGL\latebind.py", line 43, in __call__
    return self._finalCall( *args, **named )
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not callable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "e:\Document\Codes\Python\app\userInterfaces\mainWindow.py", line 61, in start
    self.appWindow = AppWindow()
                     ^^^^^^^^^^^
  File "e:\Document\Codes\Python\app\userInterfaces\appWindow.py", line 17, in __init__
    self.initializeGL()
  File "e:\Document\Codes\Python\app\userInterfaces\appWindow.py", line 55, in initializeGL
    self.vao = glGenVertexArrays(1)
               ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Roaming\Python\Python311\site-packages\OpenGL\latebind.py", line 47, in __call__
    return self._finalCall( *args, **named )
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Roaming\Python\Python311\site-packages\OpenGL\wrapper.py", line 671, in wrapperCall
    result = wrappedOperation( *cArguments )
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Roaming\Python\Python311\site-packages\OpenGL\platform\baseplatform.py", line 423, in __call__
    raise error.NullFunctionError(
OpenGL.error.NullFunctionError: Attempt to call an undefined function glGenVertexArrays, check for bool(glGenVertexArrays) before calling

我想要编写一个程序,制作如下所示的内容,并将一些游戏放入 openGl 小部件中,并使用这些按钮控制它。

expected program

我写了这个程序如下。

from OpenGL.GL import (glEnable, glMatrixMode, glClearColor, glClear, glPushMatrix, glPopMatrix, glRotate, glTranslate, glGenVertexArrays, GL_DEPTH_TEST, GL_PROJECTION, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT)
from OpenGL.GLU import gluPerspective
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PyQt6.QtWidgets import QWidget, QSizePolicy, QHBoxLayout, QVBoxLayout, QPushButton
from PyQt6.QtGui import QCloseEvent, QMouseEvent, QWheelEvent, QIcon, QKeyEvent
from PyQt6.QtCore import Qt, QPoint, QTimer, QPointF, pyqtSignal

class Window(QWidget):
    def __init__(self, parent: QWidget | None = None) -> None:
        super().__init__(parent)
        self.setupUi()
        self.initializeGL()
        self.show()

    def setupUi(self):
        self.windowWidth = 640
        self.windowHeight = 480
        screenWidth = 1920
        screenHeight = 1080
        self.setGeometry((screenWidth - windowWidth) // 2, (screenHeight - windowHeight) // 2, windowWidth, windowHeight)
        self.setWindowIcon(QIcon(".\\app.png"))
        self.setWindowTitle("App")
        self.mainLayout = QHBoxLayout()
        self.leftButtonsLayout = QVBoxLayout()
        self.cwfButton = QPushButton()
        self.leftButtonsLayout.addWidget(self.cwfButton)
        self.mainLayout.addLayout(self.leftButtonsLayout)
        self.openGlWidgetLayout = QVBoxLayout()
        self.openGLWidget = QOpenGLWidget()
        self.openGLWidget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.openGlWidgetLayout.addWidget(self.openGLWidget)
        self.mainLayout.addLayout(self.openGlWidgetLayout)
        self.rightButtonsLayout = QVBoxLayout()
        self.ccwfButton = QPushButton()
        self.rightButtonsLayout.addWidget(self.ccwfButton)
        self.mainLayout.addLayout(self.rightButtonsLayout)
        self.setLayout(self.mainLayout)

def initializeGL(self) -> None:
        screenWidth = 1920
        screenHeight = 1080
        self.rotationX, self.rotationY, self.zoom = 30, -40, -8
        self.keyList = []
        self.mousePos = QPointF(0, 0)
        self.vao = glGenVertexArrays(1)
        glEnable(GL_DEPTH_TEST)
        glMatrixMode(GL_PROJECTION)
        gluPerspective(100, (self.windowWidth/self.windowHeight), 0.5, 50.0)
        glClearColor(0.25, 0.25, 0.25, 1)
        self.app = App()
        self.timer = QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(16)
        return super().initializeGL()

    def paintGL(self) -> None:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glPushMatrix()
        glTranslate(0.0, 0.0, self.zoom)
        glRotate(self.rotationX, 1, 0, 0)
        glRotate(self.rotationY, 0, 1, 0)
        self.app.update()
        glPopMatrix()
        return super().paintGL()

我希望你能帮助我获得一些像图片这样的应用程序,例如玩一个带有四个按钮的简单蛇游戏。

python pyqt qtopengl
1个回答
0
投票

我编写了一个程序,运行一个类似于您在 Qt 设计器中设计的窗口

import sys
from OpenGL.GL import (glEnable, glMatrixMode, glClearColor, glClear, glPushMatrix, glPopMatrix, glRotate, glTranslate,
glGenVertexArrays, GL_DEPTH_TEST, GL_PROJECTION, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT)
from OpenGL.GLU import gluPerspective
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PyQt6.QtWidgets import QWidget, QSizePolicy, QHBoxLayout, QVBoxLayout, QPushButton
from PyQt6.QtCore import QTimer, QPointF
from PyQt6.QtWidgets import QApplication
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PySide6.QtWidgets import (QApplication, QHBoxLayout, QPushButton, QSizePolicy,
    QVBoxLayout, QWidget)

class Ui_Form(QWidget):
    def __init__(self, parent: QWidget | None = None) -> None:
        super().__init__(parent)
        self.setupUi()
        # self.openGLWidget.initializeGL(self.windowWidth, self.windowHeight)
        self.timer = QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(16)
        self.show()

    def setupUi(self):
        self.windowWidth = 640
        self.windowHeight = 480
        screenWidth = 1920
        screenHeight = 1080
        self.setGeometry((screenWidth - self.windowWidth) // 2, (screenHeight - self.windowHeight) // 2, self.windowWidth, self.windowHeight)
        self.horizontalLayout = QHBoxLayout()
        self.verticalLayout_2 = QVBoxLayout()
        self.pushButton_2 = QPushButton()
        self.verticalLayout_2.addWidget(self.pushButton_2)
        self.pushButton = QPushButton()
        self.verticalLayout_2.addWidget(self.pushButton)
        self.horizontalLayout.addLayout(self.verticalLayout_2)
        self.verticalLayout = QVBoxLayout()
        self.openGLWidget = QOpenGLWidget()
        sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy1.setHorizontalStretch(0)
        sizePolicy1.setVerticalStretch(0)
        sizePolicy1.setHeightForWidth(self.openGLWidget.sizePolicy().hasHeightForWidth())
        self.openGLWidget.setSizePolicy(sizePolicy1)
        self.verticalLayout.addWidget(self.openGLWidget)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.verticalLayout_3 = QVBoxLayout()
        self.pushButton_4 = QPushButton()
        self.verticalLayout_3.addWidget(self.pushButton_4)
        self.pushButton_3 = QPushButton()
        self.verticalLayout_3.addWidget(self.pushButton_3)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.setLayout(self.horizontalLayout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    mainWindow = Ui_Form()
    sys.exit(app.exec())

但是我不知道如何在 openGLWidget 中绘制你的游戏(蛇),如果你编写了游戏引擎,你需要用下面的东西替换initializeGL和paintGL函数,但我不确定这部分

class MyGLWidget(QOpenGLWidget):
    def initializeGL(self, windowWidth, windowHeight) -> None:
        self.rotationX, self.rotationY, self.zoom = 30, -40, -8
        self.keyList = []
        self.mousePos = QPointF(0, 0)
        self.vao = glGenVertexArrays(1)
        glEnable(GL_DEPTH_TEST)
        glMatrixMode(GL_PROJECTION)
        gluPerspective(100, (windowWidth / windowHeight), 0.5, 50.0)
        glClearColor(0.25, 0.25, 0.25, 1)
        self.app = App()
        return super().initializeGL()

    def paintGL(self) -> None:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glPushMatrix()
        glTranslate(0.0, 0.0, self.zoom)
        glRotate(self.rotationX, 1, 0, 0)
        glRotate(self.rotationY, 0, 1, 0)
        self.app.update()
        glPopMatrix()
        return super().paintGL()
© www.soinside.com 2019 - 2024. All rights reserved.