PySide6.QtOpenGL.QOpenGLWindow

class QOpenGLWindow

QOpenGLWindow 类是 QWindow 的一个便捷子类,用于执行 OpenGL 绘画。更多

PySide6.QtOpenGL.QOpenGLWindow 的继承图

概要

方法

虚拟方法

信号

注意

本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。

详细描述

QOpenGLWindow 是一个增强的 QWindow,它允许使用与 QOpenGLWidget 兼容的 API 轻松创建执行 OpenGL 渲染的窗口。与 QOpenGLWidget 不同,QOpenGLWindow 不依赖于 widgets 模块,并提供更好的性能。

一个典型的应用程序将继承 QOpenGLWindow 并重新实现以下虚函数:

  • initializeGL() 用于执行OpenGL资源初始化

  • resizeGL() 用于设置变换矩阵和其他依赖于窗口大小的资源

  • paintGL() 用于发出OpenGL命令或使用QPainter进行绘制

要安排重新绘制,请调用update()函数。请注意,这不会立即导致调用paintGL()。连续多次调用update()不会以任何方式改变行为。

这是一个插槽,因此可以连接到QChronoTimer::timeout()信号以执行动画。然而,在现代OpenGL世界中,依赖与显示器的垂直刷新率同步是一个更好的选择。有关交换间隔的描述,请参见setSwapInterval()。在大多数系统上,默认情况下交换间隔为1,这意味着在每次重绘后由QOpenGLWindow内部执行的swapBuffers()调用将阻塞并等待垂直同步。这意味着每当交换完成后,可以通过调用update()再次安排更新,而无需依赖计时器。

要为上下文请求特定配置,请像对任何其他QWindow一样使用setFormat()。这允许请求给定的OpenGL版本和配置文件,或启用深度和模板缓冲区。

注意

应用程序需要确保从底层窗口系统接口请求深度和模板缓冲区。如果没有请求非零的深度缓冲区大小,则不能保证深度缓冲区的可用性,因此与深度测试相关的OpenGL操作可能无法按预期工作。

常用的深度和模板缓冲区大小请求分别为24和8。例如,QOpenGLWindow子类可以在其构造函数中执行此操作:

QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
setFormat(format);

与QWindow不同,QOpenGLWindow允许在其自身上打开一个画家并执行基于QPainter的绘图。

QOpenGLWindow 支持多种更新行为。默认的 NoPartialUpdate 等同于一个常规的基于 OpenGL 的 QWindow。相比之下,PartialUpdateBlitPartialUpdateBlend 更符合 QOpenGLWidget 的工作方式,其中始终存在一个额外的专用帧缓冲对象。这些模式通过牺牲一些性能,允许每次绘制时只重绘较小的区域,并保留前一帧的其余内容。这对于使用 QPainter 进行增量渲染的应用程序非常有用,因为这样它们就不必在每次 paintGL() 调用时重绘整个窗口内容。

类似于QOpenGLWidgetQOpenGLWindow支持Qt::AA_ShareOpenGLContexts属性。当启用时,所有QOpenGLWindow实例的OpenGL上下文将相互共享。这允许访问彼此的可共享OpenGL资源。

有关Qt中图形的更多信息,请参阅Graphics。

class UpdateBehavior

此枚举描述了QOpenGLWindow的更新策略。

常量

描述

QOpenGLWindow.NoPartialUpdate

表示每次更新时整个窗口表面都会重新绘制,因此不需要额外的帧缓冲区。这是在大多数情况下使用的设置,相当于直接通过QWindow进行绘制的功能。

QOpenGLWindow.PartialUpdateBlit

表示在paintGL()中执行的绘制操作并未覆盖整个窗口。在这种情况下,系统会在后台创建一个额外的帧缓冲对象,并且在paintGL()中执行的渲染将针对此帧缓冲。每次绘制后,此帧缓冲将被复制到窗口表面的默认帧缓冲上。这允许在paintGL()中编写基于QPainter的绘制代码,该代码每次只重绘较小的区域,因为与NoPartialUpdate不同,之前的内容会被保留。

QOpenGLWindow.PartialUpdateBlend

类似于PartialUpdateBlit,但不是使用帧缓冲区的blit操作,而是通过绘制一个启用了混合的纹理四边形来渲染额外帧缓冲区的内容。与PartialUpdateBlit不同,这种方法允许alpha混合内容,并且即使在glBlitFramebuffer不可用时也能工作。在性能方面,此设置可能比PartialUpdateBlit稍慢。

__init__([updateBehavior=QOpenGLWindow.UpdateBehavior.NoPartialUpdate[, parent=None]])
Parameters:

使用给定的parentupdateBehavior构造一个新的QOpenGLWindow

另请参阅

UpdateBehavior

__init__(shareContext[, updateBehavior=QOpenGLWindow.UpdateBehavior.NoPartialUpdate[, parent=None]])
Parameters:

使用给定的parentupdateBehavior构造一个新的QOpenGLWindowQOpenGLWindow的上下文将与shareContext共享。

context()
Return type:

QOpenGLContext

返回此窗口使用的QOpenGLContext,如果尚未初始化,则返回0

defaultFramebufferObject()
Return type:

整数

此窗口使用的帧缓冲对象句柄。

当更新行为设置为NoPartialUpdate时,没有单独的帧缓冲对象。在这种情况下,返回的值是默认帧缓冲的ID。

否则为帧缓冲对象的ID值,如果尚未初始化则为0

doneCurrent()

释放上下文。

在大多数情况下,不需要调用此函数,因为小部件在调用paintGL()时会确保上下文正确绑定和释放。

另请参阅

makeCurrent()

frameSwapped()

此信号在可能阻塞的缓冲区交换完成后发出。希望与垂直刷新同步连续重绘的应用程序应在此信号上发出update()。与传统的计时器使用相比,这可以实现更流畅的体验。

grabFramebuffer()
Return type:

QImage

返回帧缓冲区的副本。

注意

这是一个可能代价高昂的操作,因为它依赖于glReadPixels()来读取像素。这可能会很慢,并且可能会阻塞GPU管道。

注意

当与更新行为NoPartialUpdate一起使用时,如果在前后缓冲区交换后调用(除非在底层窗口系统接口中启用了保留交换),返回的图像可能不包含所需的内容。在这种模式下,函数从后缓冲区读取,其内容可能与屏幕上的内容(前缓冲区)不匹配。在这种情况下,唯一可以安全使用此函数的地方是paintGL()paintOverGL()

initializeGL()

这个虚函数在第一次调用paintGL()resizeGL()之前被调用一次。在子类中重新实现它。

此函数应设置任何所需的OpenGL资源和状态。

不需要调用makeCurrent(),因为在调用此函数时已经完成了此操作。但请注意,如果使用了部分更新模式,帧缓冲区在此阶段尚不可用,因此请避免从此处发出绘制调用。将此类调用推迟到paintGL()

另请参阅

paintGL() resizeGL()

isValid()
Return type:

布尔

如果窗口的OpenGL资源(如上下文)已成功初始化,则返回true。请注意,在窗口变为暴露(显示)之前,返回值始终为false

makeCurrent()

通过使相应的上下文成为当前上下文并绑定帧缓冲对象(如果有的话),为该窗口准备渲染OpenGL内容。

在大多数情况下不需要调用此函数,因为它会在调用paintGL()之前自动调用。尽管如此,它仍然被提供以支持高级的多线程场景,其中不同于GUI或主线程的线程可能希望更新表面或帧缓冲区内容。有关线程相关问题的更多信息,请参见QOpenGLContext。

此函数也适用于在底层平台窗口已被销毁时调用。这意味着从QOpenGLWindow子类的析构函数中调用此函数是安全的。如果没有本地窗口,则使用离屏表面代替。这确保了只要首先调用此函数,析构函数中的OpenGL资源清理操作将始终有效。

paintGL()

每当需要绘制窗口内容时,都会调用此虚拟函数。在子类中重新实现它。

不需要调用makeCurrent(),因为在调用此函数时已经完成了此操作。

在调用此函数之前,上下文和帧缓冲区(如果有的话)会被绑定,并且通过调用glViewport()来设置视口。框架不会设置其他状态,也不会执行清除或绘制操作。

注意

当使用部分更新行为时,例如PartialUpdateBlend,前一次paintGL()调用的输出会被保留,并且在当前函数调用中执行了额外的绘制后,内容会被复制或混合到直接在窗口中绘制的内容上,如paintUnderGL()所示。

paintOverGL()

这个虚函数在每次调用 paintGL() 之后被调用。

当更新模式设置为 NoPartialUpdate 时,此函数与 paintGL() 之间没有区别,在它们中的任何一个执行渲染都会导致相同的结果。

paintUnderGL() 类似,此函数中的渲染目标是窗口的默认帧缓冲区,无论更新行为如何。它在 paintGL() 返回并且完成了 blit(PartialUpdateBlit)或四边形绘制(PartialUpdateBlend)之后被调用。

paintUnderGL()

虚拟函数在每次调用 paintGL() 之前被调用。

当更新模式设置为NoPartialUpdate时,此函数与paintGL()之间没有区别,在它们中的任何一个执行渲染都会导致相同的结果。

当使用PartialUpdateBlend时,差异变得显著,因为使用了额外的帧缓冲对象。在那里,paintGL()针对这个额外的帧缓冲对象,它保留了其内容,而paintUnderGL()和paintOverGL()则针对默认的帧缓冲,即直接针对窗口表面,其内容在每一帧显示后都会丢失。

注意

当更新行为为PartialUpdateBlit时,避免依赖此函数。此模式涉及在每次调用paintGL()后,将paintGL()使用的额外帧缓冲区blit到默认帧缓冲区上,从而覆盖在此函数中生成的所有绘图。

resizeGL(w, h)
Parameters:
  • w – 整数

  • h – 整数

每当小部件调整大小时,都会调用此虚拟函数。在子类中重新实现它。新的大小通过 wh 传递。

注意

这仅仅是一个为了方便提供与QOpenGLWidget兼容的API的函数。与QOpenGLWidget不同,派生类可以选择覆盖resizeEvent()而不是这个函数。

注意

避免从此函数发出OpenGL命令,因为在调用时可能没有当前上下文。如果无法避免,请调用makeCurrent()

注意

从这里安排更新是不必要的。窗口系统将发送暴露事件,自动触发更新。

另请参阅

initializeGL() paintGL()

shareContext()
Return type:

QOpenGLContext

返回请求与此窗口的QOpenGLContext共享的QOpenGLContext。

updateBehavior()
Return type:

UpdateBehavior

返回此QOpenGLWindow的更新行为。