在QML中拍摄特定项目的屏幕截图的方式是什么?
I know how to take a screenshot of the whole window in QML。在QML中拍摄特定项目的屏幕截图的方式是什么?
我在QML窗口中有一个Video
元素。该视频显示在Rectangle
中。
什么是采取的是Rectangle
,而不是整个窗口截图的方式吗?
看看Item
的grabToImage
方法。
bool grabToImage(callback, targetSize)
抓斗所述项目插入到内存中的图像。
抓取发生异步,抓取完成时调用JavaScript函数回调 。
使用targetSize指定目标图像的大小。默认情况下, 结果将具有与该项目相同的大小。
如果抓取无法启动,该函数返回false。
以下片段显示如何抓取项目并将结果 存储到文件。
Rectangle {
id: source
width: 100
height: 100
gradient: Gradient {
GradientStop { position: 0; color: "steelblue" }
GradientStop { position: 1; color: "black" }
}
}
// ...
source.grabToImage(function(result) {
result.saveToFile("something.png");
});
下面的代码片断示出了如何抓住一个项目,并在另一 图像元素使用的结果。
Image {
id: image
}
// ...
source.grabToImage(function(result) {
image.source = result.url;
},
Qt.size(50, 50));
注:该功能可以将项渲染到屏幕外表面和 复制从GPU的内存到CPU的内存, 可以是相当昂贵的表面。对于“实时”预览,请使用ShaderEffectSource图层或 。
这与QtQuick 2.0一起使用。
您可以使用grabWindow()
方法,然后裁剪生成的图像。您需要在窗口中找到QML元素的绝对位置,只需获取其位置并将其添加到每个父元素的位置,直到您点击根元素,然后使用QImage::copy(x, y, w, h)
将窗口图像裁剪到元素位置并尺寸。
这样做有一些缺点 - 它比较慢,因为它具有抓取整个窗口和裁剪的开销,并且如果您的元素不是矩形和不透明的,它还会抓取元素下可见的东西。但如果它是一个不透明的矩形,并且性能不是问题,那么这是一个简单的方法。
困难但速度更快的方法:您可以使用在QML中创建ShaderEffectSource
并将其sourceItem
设置为所需的元素。这将有效地将该元素渲染到纹理中,以便您可以使用它的着色器效果。然后在C++端,从QQuickShaderEffectSource
可以使用其QSGTextureProvider *textureProvider()
方法获取纹理提供程序,然后使用QSGTexture * QSGTextureProvider::texture()
获取纹理,并从纹理中可以找到纹理标识int QSGTexture::textureId()
。最后,你可以get an image from the texture id并使用原始数据构建一个QImage
。
请分享ShaderEffectSource解决方案的代码吗? – mabg
这是一个非常有趣的问题。作为一种快速而有效的解决方案,我可以建议您使用Item
的grabToImage
方法。它将第一个参数作为回调函数,第二个参数作为要保存的路径。
我写的小功能,用于抓取任何Item
:
// what -- name of item needed to be grabbed
// where -- string
function render(what, where) {
// Find existent item with given name `what`
var i = 0
var found = false
for (i = 0; i < window.contentItem.children.length; i++) {
if (window.contentItem.children[i].objectName === what) {
// We found respective item
found = true
break
}
}
if (found) {
console.log("We found item " + what + ". Grabbing it to " + where)
var item = window.contentItem.children[i]
// Grab image and save it (via callback f-ion)
item.grabToImage(function(result) { result.saveToFile(where) })
} else {
console.warn("No item called " + what)
}
}
所以你可以使用它作为QML/QtQuick的一面,Qt的(使用QMetaObject::invokeMethod
)。
还有QQuickItem::grabToImage
方法,但我会很高兴地看到其使用的任何适当的例子。
做抢的另一种方法是使用ShaderEffectSource
并按你的意愿使用。
所有我上面准备作为一个项目,位于github写道。代码被评论,所以希望所有人都会清楚。你可以拿它并做一些黑客行为。拉请求也是受欢迎的。
** ShaderEffectSource真的更快吗?从Qt文档中看起来并不是这样**尽管[ShaderEffectSource]的官方文档(http://doc.qt.io/qt-5/qml-qtquick-shadereffectsource.html)明确指出带有* Warning *标签在大多数情况下,它会降低性能并增加视频内存使用量。你能澄清一下吗?我正在寻找最快的方式来保存图像。我也看到Qt官方文档指出'ShaderEffectSource'依赖于底层硬件,并且可能在所有设备上都没有相同的功能,特别是如果您的QtApp在多种Android设备上运行。 –