I know how to take a screenshot of the whole window in QML
我在QML窗口中有一个Video
元素。该视频显示在Rectangle
中。
如何截取 的Rectangle
而不是整个窗口的屏幕截图?
答案 0 :(得分:5)
这是一个非常有趣的问题。作为一种快速且有效的解决方案,我建议您使用grabToImage
Item
方法。它将第一个参数作为回调函数,第二个参数作为要保存的路径。
我写了一个小函数来抓取任何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。代码被评论,所以希望一切都清楚。你可以接受并做一些黑客攻击。欢迎提出拉动请求。
答案 1 :(得分:3)
查看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的内存中 可能是相当昂贵的。对于&#34;直播&#34;预览,使用图层或 ShaderEffectSource。
这也适用于 QtQuick 2.0 。
答案 2 :(得分:0)
您可以使用grabWindow()
方法,然后裁剪生成的图像。您需要在窗口上找到QML元素的绝对位置,只需获取其位置并将其添加到每个父元素的位置,直到您点击根元素,然后使用QImage::copy(x, y, w, h)
将窗口图像裁剪为元素的位置和大小。
这有一些缺点 - 它较慢,因为它有抓住整个窗口和裁剪的开销,如果你的元素不是矩形和不透明,它也会抓住元素下可见的东西。但如果它是一个不透明的矩形,并且性能不是问题,那么这就是它的简单方法。
更难但更快的方法:您可以使用在QML中创建ShaderEffectSource
并将其sourceItem
设置为您想要的元素。这将有效地将该元素渲染为纹理,因此您可以对其使用着色器效果。然后在C ++方面,从QQuickShaderEffectSource
你可以使用它的QSGTextureProvider *textureProvider()
方法来获取纹理提供者,然后从中使用QSGTexture * QSGTextureProvider::texture()
来获取纹理,从纹理中你可以找到纹理ID为int QSGTexture::textureId()
。最后,您可以get an image from the texture id并使用原始数据构建QImage
。