![](/img/trans.png)
[英]Qt : How to grab a snapshot of a QQuickItem leaving out its child QQuickItems from the grabbed result
[英]Qt: How to merge 2 QQuickItems into one before saving it into a png
通過對StackOverflow的討論 ,我可以將QML項目中的圖像作為png/jpeg
保存到文件中。
如何疊加或合並兩個不同的qml
圖層並將它們合並為一個,將其保存到png / jpeg中?
注意:我可以保存一個QQuickItem
。 只需知道如何覆蓋2 QQuickItem
s
只需將兩個qml對象作為根Item
子Item
,然后獲取該根項,它將捕獲其所有內容。
只需確保根項目足夠大以包圍子項,並且子項不在負空間中,因為它只捕獲根項目的足跡內部。
您也可以使用C ++甚至QML進行手動合成。
你評論中描述的問題是你不能移動東西,所以你能做什么? 您可以擁有兩個Image
元素,而不是將原始QML對象作為同一根的父元素,然后捕獲項目A並將捕獲結果設置為圖像A的源,然后對項目B執行相同操作,最后,捕獲根項目,將兩個圖像一起捕獲。
好的,這是一個簡單的例子,它看起來有點復雜,因為抓取是異步的,你必須等待各個抓取結果完成才能獲得“最終”根項,從而使用計時器。 在此示例中,不同的項目排成一行,但您可以按照自己喜歡的方式組合它們:
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
Rectangle {
id: s1
visible: false
width: 200
height: 200
color: "red"
}
Rectangle {
id: s2
visible: false
width: 200
height: 200
color: "blue"
}
Row {
id: joiner
visible: false
Image { id: t1 }
Image { id: t2 }
}
Image {
id: result
y: 200
}
Timer {
id: finish
interval: 10
onTriggered: joiner.grabToImage(function(res) {result.source = res.url})
}
Component.onCompleted: {
s1.grabToImage(function(res) {t1.source = res.url})
s2.grabToImage(function(res) {t2.source = res.url; finish.start() })
}
}
首先捕獲兩個矩形並將其用作木匠中圖像的源,然后捕獲木匠並在結果圖像中顯示,除最終結果圖像之外的所有對象都被隱藏。
更簡單的是,您可以使用這個漂亮的小幫手快速加入單個圖像中的任意數量的項目:
Item {
id: joinHelper
visible: false
property Component ic: Image { }
property var cb: null
Row { id: joiner }
Timer {
id: finish
interval: 100
onTriggered: joiner.grabToImage(joinHelper.cb)
}
function join(callback) {
if (arguments.length < 2) return // no items were passed
var i
if (joiner.children.length) { // clean previous captures
for (i = 0; i < joiner.children.length; ++i) {
joiner.children[i].destroy()
}
}
cb = callback // set callback for later
for (i = 1; i < arguments.length; ++i) { // for every item passed
var img = ic.createObject(joiner) // create empty image
// need to capture img by "value" because of JS scoping rules
// otherwise you end up with only one image - the final one
arguments[i].grabToImage(function(temp){ return function(res){temp.source = res.url}}(img))
}
finish.start() // trigger the finishing step
}
}
你這樣使用它:
joinHelper.join(function(res) { result.source = res.url }, s1, s2)
它仍然使用一行,但您可以輕松調整它以進行自己的布局。 它通過傳遞最終回調和你想要捕獲的所有項目來工作,在內部它為每個項目創建一個圖像,將它們放入容器中,然后觸發完成計時器。
請注意,根據系統的速度和項目的復雜程度以及計數的大小,您可能需要延長計時器間隔,因為最終的回調需要在所有捕獲完成后才執行,圖像源已分配並調整圖像大小以使行具有適當的尺寸。
我還注釋了大多數事情,以便更容易理解。
這個問題似乎是密切相關的這一個
解決方案是將有問題的Item
渲染為第二個項目的紋理,您無需渲染到屏幕。 您可以撰寫這個Item
,只要你想通過添加多個ShaderEffectSource
S作為孩子,只要你喜歡它們相對定位到對方,並設置其來源的Item
要搶圖像S。
然后你抓住Item
to Image。
一個通用示例,它公開一個函數以將Item
的列表抓取到一個Image,其中每個Item
堆疊在彼此的頂部,每個不透明度為0.2:
import QtQuick 2.0
Rectangle {
id: root
visible: false
color: 'white'
function grabMultipleToImage(url, objects) {
imgRep.url = url
width = Math.max.apply(root, objects.map(function(e) { return e.width }))
height = Math.max.apply(root, objects.map(function(e) { return e.height }))
imgRep.ready = 0
imgRep.model = objects
}
Repeater {
id: imgRep
onReadyChanged: {
if (ready > 0 && ready === model.length) {
console.log(root.width, root.height, imgRep.url)
root.grabToImage(function (res) { res.saveToFile(imgRep.url); model = null })
}
}
property int ready: 0
property string url
delegate: ShaderEffectSource {
sourceItem: modelData
width: modelData.width
height: modelData.height
opacity: 0.2
live: false
Component.onCompleted: { imgRep.ready++ }
}
}
}
使用這個將是這樣的:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: myWindow
visible: true
width: 600
height: 600
color: 'white'
Button {
text: 'grab'
onClicked: {
test.grabMultipleToImage('testimg.jpg', [rect1, rect2, rect3])
}
}
ImageGrabber {
id: test
}
Rectangle {
x: 100
y: 205
id: rect1
color: 'blue'
width: 10
height: 20
}
Rectangle {
x: 250
y: 12
id: rect2
color: 'green'
width: 20
height: 30
}
Rectangle {
x: 100
y: 100
id: rect3
color: 'red'
width: 100
height: 5
}
}
但是如果你需要更復雜的合並,你也可以手動創建這個對象並隨時抓取它。
根據文檔中的說明,不計量
注意 :此功能會將項目渲染到屏幕外表面,並將該表面從GPU的內存復制到CPU的內存中,這可能非常昂貴。 對於“實時”預覽,請使用圖層或ShaderEffectSource。
這個解決方案應該比使用帶有ItemGrabResult
的Image
更高效,因為它可以將內容保存在GPU內存中,直到它被抓取並存儲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.