带有 OpenGL 的 Qt MDI 应用程序:如何获取有效的屏幕截图?

Posted

技术标签:

【中文标题】带有 OpenGL 的 Qt MDI 应用程序:如何获取有效的屏幕截图?【英文标题】:Qt MDI app with OpenGL: how to grab a valid screenshot? 【发布时间】:2009-08-27 07:19:25 【问题描述】:

我有一个用 Qt 编写的 MDI 应用程序。一些子窗口包括QGLWidgets,即 OpenGL 上下文。其中最突出的是使用 OpenGL 顶点和片段着色器来可视化其数据。

我需要以编程方式捕获应用程序主窗口的屏幕截图,当然包括所有碰巧可见的子窗口。一开始听起来很容易(“肯定被问过很多次了,所以让我们谷歌一下吧!”),但仔细一看似乎有点棘手......

这是我迄今为止尝试过的:

    QPixmap::grabWidget 不适用于使用着色器程序的子窗口,显然是因为重定向上下文似乎不支持必要的 OpenGL 扩展。 (渲染代码检查关联的上下文是否支持所需的扩展,如果不支持则拒绝继续。) QPixmap::grabWindow 默默地将所有 OpenGL 上下文留空——即使是那些仅使用基本图元的上下文。 QGLWidget::grabFrameBuffer 有效,但仅捕获特定子窗口的 OpenGL 上下文,而我想获取整个应用程序(基本上是 Alt+PrtScr 在 Windows 中所做的)。

我还尝试先执行 #2,然后为所有子窗口迭代 #3,只需将 #3 的结果从 #2 复制到图像的正确位置。这工作得很好,直到我让一些子窗口重叠——在这种情况下,来自 #3 的图像会覆盖子窗口框架等。所以这种方法可能需要更多的代码来处理所有令人讨厌的极端情况......

一些额外的背景:一旦我得到截图,我将把其中的几个放在一个序列中以创建一个视频——可能使用ffmpeg。这使得这个问题成为my previous question(的第一部分)的一种延续;只是该应用程序已从单上下文独立 OpenGL 程序发展为使用 Qt 进行整体窗口和 UI 小部件的东西,并将图形嵌入子窗口中。

虽然我当然更喜欢一个不错的 Qt-ish 跨平台解决方案,但我也愿意考虑使用 Windows 特定的 hack。 (这应该是可能的,因为我可以看到 Alt+PrtScr 做了非常正确的事情。)

那么,有什么建议吗?

【问题讨论】:

【参考方案1】:

非常 hackish,但是否像在 this tutorial 中一样捕获桌面(不隐藏窗口)并裁剪除窗口之外的所有内容?

更一般地说,我什至不确定 OpenGL 规范是否要求必须将输出放置在前端缓冲区中:实现可以只使用视频覆盖(或 Voodoo2 式 VGA 直通恶作剧)进行输出。

【讨论】:

确实工作!现在为什么我自己不能想到这个? ...我看到的唯一缺点是,与仅抓取感兴趣的窗口相比,这基本上要慢一些。这可能是相关的,因为我实际上是在尝试获取视频。但无论如何我都会接受答案,因为它完全符合我的要求——非常感谢!【参考方案2】:

我唯一能想到的就是做以下伪代码:

 for each window
     grab the window into its own pixmap
     grab the GL portions and paste into the windows
 order the window pixmaps by depth of the window (deepest first)
 initialize a common pixmap
 for each window pixmap
     paint the window pixmap into the common pixmap at the appropriate location.

【讨论】:

我同意这应该可行,因此 +1。但至少现在,我要走懒惰的路:)【参考方案3】:

这有用吗?The Grabber examples shows how to retrieve the contents of an OpenGL framebuffer

【讨论】:

它使用grabFrameBuffer(),因此只捕获OpenGL视口。请参阅问题中的第 3 项。

以上是关于带有 OpenGL 的 Qt MDI 应用程序:如何获取有效的屏幕截图?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Qt 5 安装 OpenGL

带有 QT 错误的 OpenGL:断言:“QOpenGLFunctions::isInitialized(d_ptr)”。无法创建 OpenGL 上下文

带有 Qt 和 OpenGL 的轨迹球控件

Qt5.5下捕获一个带有OpenGL内容的Widget

Qt 5.1 带有共享 QGLWidgets 的线程化 OpenGL

如何在带有 Qt 的 OpenGL 中使用顶点缓冲区对象绘制矩形?