PyQt6/PySide6中关闭窗口后resizeGL的glViewport报‘Invalid operation’错误
解决PyQt6/PySide6中关闭窗口时resizeGL触发OpenGL无效操作错误
问题原因
窗口关闭流程中,OpenGL上下文可能已被销毁,但Qt仍会触发resizeGL事件。此时调用glViewport等OpenGL函数,因缺少有效上下文,会抛出Invalid operation错误。
修复方案
以下两种方式均可解决该问题:
方案1:在resizeGL中检查上下文有效性
修改resizeGL方法,先确认当前OpenGL上下文有效后再执行OpenGL操作:
import sys from OpenGL.GL import * from PyQt6.QtCore import Qt from PyQt6.QtOpenGL import QOpenGLWindow from PyQt6.QtWidgets import QApplication class OpenGLWindow(QOpenGLWindow): def __init__(self): super().__init__() def initializeGL(self): glClearColor(0.2, 0.2, 0.2, 1) def resizeGL(self, w, h): # 检查OpenGL上下文是否有效 if self.context().isValid(): glViewport(0, 0, w, h) def paintGL(self): # 同样添加上下文检查,避免关闭时paintGL报错 if self.context().isValid(): glClear(GL_COLOR_BUFFER_BIT) if __name__ == "__main__": QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL) app = QApplication(sys.argv) w = OpenGLWindow() w.show() sys.exit(app.exec())
方案2:通过关闭标志控制resizeGL执行
添加关闭状态标志,在closeEvent中标记窗口正在关闭,resizeGL中判断该标志后跳过操作:
import sys from OpenGL.GL import * from PyQt6.QtCore import Qt from PyQt6.QtGui import QCloseEvent from PyQt6.QtOpenGL import QOpenGLWindow from PyQt6.QtWidgets import QApplication class OpenGLWindow(QOpenGLWindow): def __init__(self): super().__init__() self._is_closing = False def initializeGL(self): glClearColor(0.2, 0.2, 0.2, 1) def resizeGL(self, w, h): if not self._is_closing: glViewport(0, 0, w, h) def paintGL(self): if not self._is_closing: glClear(GL_COLOR_BUFFER_BIT) def closeEvent(self, event: QCloseEvent) -> None: self._is_closing = True super().closeEvent(event) if __name__ == "__main__": QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL) app = QApplication(sys.argv) w = OpenGLWindow() w.show() sys.exit(app.exec())
说明
方案1直接检查上下文状态,贴合OpenGL操作的本质逻辑;方案2通过状态标志控制,代码逻辑更直观。两种方案都能有效避免窗口关闭时的无效OpenGL调用错误。
内容的提问来源于stack exchange,提问作者8Observer8
相关产品推荐
相关产品推荐

