class QOpenGLWindow#

The QOpenGLWindow class is a convenience subclass of QWindow to perform OpenGL painting. More

Inheritance diagram of PySide6.QtOpenGL.QOpenGLWindow

Synopsis#

Methods#

虚方法#

信号#

注意

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

详细描述#

QOpenGLWindow 是一个增强了的 QWindow,允许通过兼容 QOpenGLWidget 的 API 简单地创建OpenGL渲染的窗口。与 QOpenGLWidget 不同,QOpenGLWindow 没有依赖于小部件模块,并提供了更好的性能。

典型应用将子类化 QOpenGLWindow 并重写以下虚函数

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

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

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

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

这是一个槽,因此它可以连接到QTimer::timeout()信号以执行动画。然而,在现代OpenGL环境中,更好地选择依赖于同步到显示屏的垂直刷新率。请参阅setSwapInterval()获取有关交换间隔的描述。默认情况下,大多数系统使用1作为交换间隔,这会导致 QOpenGLWindow 在每次绘制后执行的swapBuffers()调用阻塞并等待vsync。这意味着在交换完成时,可以通过调用update()来安排再次重绘,而无需依赖定时器。

要请求特定配置的上下文,使用setFormat()像任何其他QWindow一样。这允许请求特定的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() 调用时重新绘制整个窗口内容。

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

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

class UpdateBehavior#

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

常量

说明

QOpenGLWindow.NoPartialUpdate

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

QOpenGLWindow.PartialUpdateBlit

表示在paintGL() 中执行绘制的范围并不覆盖整个窗口。在这种情况下,后台创建了一个额外的帧缓冲区对象,并在paintGL() 中执行的渲染将针对这个帧缓冲区。然后在每次绘制后将此帧缓冲区粘贴到窗口表面的默认帧缓冲区上。这允许在paintGL() 中使用基于QPainter的绘制代码,每次只重新绘制较小的区域,因为,与 NoPartialUpdate 不同,之前的内容得到保留。

QOpenGLWindow.PartialUpdateBlend

与 PartialUpdateBlit 类似,但不是使用帧缓冲区复制,而是通过启用混合绘制纹理四边形来渲染额外的帧缓冲区的包含内容。与 PartialUpdateBlit 不同,这允许Alpha混合内容,并且即使在夹 glBlitFramebuffer 不可用的情况下也能工作。在性能方面,此设置可能比 PartialUpdateBlit 稍慢。

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

使用指定的parentupdateBehavior构建一个新的QOpenGLWindow。新的QOpenGLWindow上下文将与shareContext共享。

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

使用指定的parentupdateBehavior构建一个新的QOpenGLWindow

参见

更新行为

context()#
返回类型

QOpenGLContext

返回此窗口所用的QOpenGLContext或0,如果尚未初始化。

defaultFramebufferObject()#
返回类型

int

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

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

在其他情况下,返回帧缓冲区对象的ID或0,如果尚未初始化。

doneCurrent()#

释放上下文。

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

参见

makeCurrent()

frameSwapped()#

在潜在的阻塞缓冲区交换完成后发出此信号。希望与垂直刷新同步持续重绘的应用程序应在接收到此信号后发出update()。这与传统定时器的使用相比,可以使体验更加平滑。

grabFramebuffer()#
返回类型

QImage

返回帧缓冲区的副本。

注意

这是一个可能成本高昂的操作,因为它依赖于glReadPixels()来读取像素。这可能会很慢并阻塞GPU流水线。

注意

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

initializeGL()#

此虚函数在首次调用paintGL()resizeGL()之前调用一次。在子类中重新实现它。

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

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

isValid()#
返回类型

bool

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

makeCurrent()#

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

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

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

paintGL()#

这个虚拟函数会在需要绘制窗口内容时被调用。在子类中重写它。

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

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

注意

当使用类似PartialUpdateBlend的局部更新行为时,上一个paintGL()调用的输出会被保留。在当前的函数调用中执行附加绘制后,内容会在paintUnderGL()中将内容绘制到窗口上的内容上执行复制或混合。

paintOverGL()#

此虚拟函数在每次调用paintGL()后都会被调用。

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

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

paintUnderGL()#

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

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

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

注意

当更新行为设置为 PartialUpdateBlit 时,应避免依赖于此函数。此模式涉及在每个调用 paintGL() 之后,将 paintGL() 使用的额外帧缓冲区像素块映射到默认帧缓冲区上,从而覆盖在此函数中产生的所有绘图。

resizeGL(w, h)#
参数::
  • – 整数

  • – 整数

此虚拟函数在部件大小改变时被调用。在子类中重新实现它。新大小通过 wh 传递。

注意

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

注意

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

注意

从此处安排更新是不必要的。窗口系统将发送显式事件以自动触发更新。

shareContext()#
返回类型

QOpenGLContext

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

updateBehavior()#
返回类型

更新行为

返回本 QOpenGLWindow 的更新行为。