QOpenGLWindow Class

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

Header: #include <QOpenGLWindow>
CMake: find_package(Qt6 REQUIRED COMPONENTS OpenGL)
target_link_libraries(mytarget PRIVATE Qt6::OpenGL)
qmake: QT += opengl
继承: QPaintDeviceWindow

公共类型

enum UpdateBehavior { NoPartialUpdate, PartialUpdateBlit, PartialUpdateBlend }

公共函数

QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
QOpenGLWindow(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
virtual ~QOpenGLWindow()
QOpenGLContext *context() const
GLuint defaultFramebufferObject() const
void doneCurrent()
QImage grabFramebuffer()
bool isValid() const
void makeCurrent()
QOpenGLContext *shareContext() const
QOpenGLWindow::UpdateBehavior updateBehavior() const

信号

void frameSwapped()

受保护函数

virtual void initializeGL()
virtual void paintGL()
virtual void paintOverGL()
virtual void paintUnderGL()
virtual void resizeGL(int w, int h)

重新实现的受保护函数

virtual void paintEvent(QPaintEvent *event) override
virtual void resizeEvent(QResizeEvent *event) override

详细说明

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

一个典型的应用程序将对 QOpenGLWindow 进行子类化,并重新实现以下虚拟函数:

  • initializeGL() 用于执行 OpenGL 资源初始化
  • resizeGL() 设置变换矩阵和其他与窗口大小相关的资源
  • paintGL() 用于发出 OpenGL 命令或使用 OpenGL 绘图。QPainter

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

这是一个槽,因此可以连接到QChronoTimer::timeout() 信号来执行动画。但请注意,在现代 OpenGL 世界中,与显示器的垂直刷新率同步是更好的选择。有关交换间隔的描述,请参阅setSwapInterval() 。如果交换间隔为1 (大多数系统的默认情况),QOpenGLWindow 在每次重绘后内部执行的swapBuffers() 调用将阻塞并等待 vsync。这意味着只要交换完成,就可以通过调用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() 时重绘整个窗口内容。

QOpenGLWidget 类似,QOpenGLWindow 也支持Qt::AA_ShareOpenGLContexts 属性。启用后,所有 QOpenGLWindow 实例的 OpenGL 上下文将相互共享。这样就可以访问彼此可共享的 OpenGL 资源。

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

成员类型文档

enum QOpenGLWindow::UpdateBehavior

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

常量说明
QOpenGLWindow::NoPartialUpdate0表示每次更新时将重新绘制整个窗口表面,因此不需要额外的帧缓冲区。这是大多数情况下使用的设置,相当于直接通过QWindow 进行绘制的功能。
QOpenGLWindow::PartialUpdateBlit1表示在paintGL() 中执行的绘制没有覆盖整个窗口。在这种情况下,会在引擎盖下创建一个额外的帧缓冲对象,在paintGL() 中执行的渲染将以该帧缓冲为目标。每次绘制后,该帧缓冲都会晕染到窗口表面的默认帧缓冲上。这样,paintGL() 中基于QPainter 的绘制代码每次只重新绘制一个较小的区域,因为与 NoPartialUpdate 不同的是,之前的内容会保留下来。
QOpenGLWindow::PartialUpdateBlend2与 PartialUpdateBlit 类似,但不是使用帧缓冲区混合,而是通过绘制启用了混合功能的纹理四边形来渲染额外帧缓冲区的内容。与 PartialUpdateBlit 不同的是,它允许使用 alpha 混合内容,即使在 glBlitFramebuffer 不可用的情况下也能正常工作。从性能上看,此设置可能比 PartialUpdateBlit 稍慢。

成员函数文档

[explicit] QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)

使用给定的parentupdateBehavior 构建一个新的 QOpenGLWindow。

另请参见 QOpenGLWindow::UpdateBehavior

[explicit] QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)

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

另请参见 QOpenGLWindow::UpdateBehaviorshareContext

[virtual noexcept] QOpenGLWindow::~QOpenGLWindow()

销毁QOpenGLWindow 实例,释放其资源。

在析构函数中,OpenGLWindow 的上下文是当前的,这样就可以安全地销毁任何可能需要释放属于此窗口提供的上下文的 OpenGL 资源的子对象。

警告: 如果将封装 OpenGL 资源的对象(如QOpenGLBufferQOpenGLShaderProgram 等)作为QOpenGLWindow 子类的成员,可能还需要在该子类的析构函数中添加对makeCurrent() 的调用。根据 C++ 对象销毁的规则,这些对象将调用此函数之前销毁(但在子类的析构函数运行之后),因此在此函数中将 OpenGL 上下文设置为当前状态为时已晚,无法安全地处理这些对象。

另请参见 makeCurrent

QOpenGLContext *QOpenGLWindow::context() const

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

GLuint QOpenGLWindow::defaultFramebufferObject() const

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

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

否则,返回 framebuffer 对象 ID 的值,如果尚未初始化,则返回0

void QOpenGLWindow::doneCurrent()

释放上下文。

在大多数情况下无需调用此函数,因为在调用paintGL() 时,widget 会确保上下文已正确绑定和释放。

另请参阅 makeCurrent()。

[signal] void QOpenGLWindow::frameSwapped()

该信号在可能阻塞的buffer swap 完成后发出。如果应用程序希望与垂直刷新同步持续重绘,则应在收到此信号后发出update() 信号。与传统的定时器相比,这将带来更流畅的体验。

QImage QOpenGLWindow::grabFramebuffer()

返回帧缓冲的副本。

注意: 这是一个潜在的昂贵操作,因为它依赖 glReadPixels() 来读取像素。这可能会很慢,并可能导致 GPU 流水线停滞。

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

[virtual protected] void QOpenGLWindow::initializeGL()

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

该函数应设置所需的 OpenGL 资源和状态。

无需调用makeCurrent() ,因为在调用该函数时已经完成了设置。但请注意,在使用部分更新模式的情况下,帧缓冲区在此阶段尚未可用,因此应避免在此处发出绘制调用。请将此类调用推迟到paintGL() 进行。

另请参见 paintGL() 和resizeGL()。

bool QOpenGLWindow::isValid() const

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

void QOpenGLWindow::makeCurrent()

将相应的上下文设置为当前,并将帧缓冲对象(如果有)绑定到该上下文中,为渲染该窗口的 OpenGL 内容做好准备。

在大多数情况下无需调用该函数,因为在调用paintGL() 之前会自动调用该函数。不过,在不同于图形用户界面或主线程的线程可能希望更新曲面或帧缓冲区内容时,我们还是提供了该函数以支持高级多线程方案。有关线程相关问题的更多信息,请参见QOpenGLContext

该函数也适合在底层平台窗口已被销毁的情况下调用。这意味着从QOpenGLWindow 子类的析构函数调用该函数是安全的。如果不再有本地窗口,则会使用屏幕外表面来代替。只要首先调用此函数,就能确保析构函数中的 OpenGL 资源清理操作始终有效。

另请参阅 QOpenGLContext,context(),paintGL() 和doneCurrent() 。

[override virtual protected] void QOpenGLWindow::paintEvent(QPaintEvent *event)

重实现:QPaintDeviceWindow::paintEvent(QPaintEvent *event).

油漆event 处理程序。调用paintGL().

另请参阅 paintGL().

[virtual protected] void QOpenGLWindow::paintGL()

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

无需调用makeCurrent() ,因为在调用该函数时已经完成了绘制。

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

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

另请参阅 initializeGL()、resizeGL()、paintUnderGL()、paintOverGL() 和UpdateBehavior

[virtual protected] void QOpenGLWindow::paintOverGL()

每次调用paintGL() 后,都会调用该虚拟函数。

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

paintUnderGL() 一样,无论更新行为如何,该函数都以窗口的默认帧缓冲区为目标进行渲染。它将在paintGL() 返回、blit (PartialUpdateBlit) 或 quad drawing (PartialUpdateBlend) 完成后被调用。

另请参见 paintGL()、paintUnderGL() 和UpdateBehavior

[virtual protected] void QOpenGLWindow::paintUnderGL()

每次调用paintGL() 之前都会调用该虚拟函数。

当更新模式设置为NoPartialUpdate 时,该函数与paintGL() 没有任何区别,使用它们进行渲染的结果都是一样的。

当使用PartialUpdateBlend 时,两者的区别就变得非常明显,因为在这里使用了一个额外的帧缓冲对象。paintGL()以这个额外的帧缓冲对象为目标,保留其内容,而 paintUnderGL()和paintOverGL()以默认帧缓冲为目标,即直接以窗口表面为目标,其内容在每显示一帧后都会丢失。

注意: 当更新行为为PartialUpdateBlit 时,请避免依赖该函数。该模式包括在每次调用paintGL() 后,将paintGL() 使用的额外帧缓冲区混合到默认帧缓冲区中,从而覆盖该函数生成的所有绘图。

另请参见 paintGL()、paintOverGL() 和UpdateBehavior

[override virtual protected] void QOpenGLWindow::resizeEvent(QResizeEvent *event)

重实现:QWindow::resizeEvent(QResizeEvent *ev)。

调整event 处理程序。调用resizeGL().

另请参阅 resizeGL().

[virtual protected] void QOpenGLWindow::resizeGL(int w, int h)

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

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

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

注意: 没有必要在此处安排更新。视窗系统会自动发送触发更新的暴露事件。

另请参阅 initializeGL() 和paintGL()。

QOpenGLContext *QOpenGLWindow::shareContext() const

返回要求与此窗口共享的QOpenGLContext QOpenGLContext

QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const

返回QOpenGLWindow 的更新行为。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.