QML如何绘制不同的grabToImage()
Posted
技术标签:
【中文标题】QML如何绘制不同的grabToImage()【英文标题】:QML How to paint different to grabToImage() 【发布时间】:2017-05-22 18:47:38 【问题描述】:是否有任何可能的方法使grabToImage()
缓冲区与 GUI 中显示的缓冲区不同?我在 GUI 中使用ChartView
没有图例,并希望将其导出到带有图例的PNG
。所以我尝试:
chartView.legend.visible = true
chartView.update()
chartView.grabToImage(function(result)
console.log("grabbed")
var path = filename.toString().replace(/^(file:\/2)/,"");
console.log(path + result.saveToFile(path));
chartView.legend.visible = false
update();
);
但这两个更新仅在控件退出此功能后才会发生,所以我没有在 PNG 中绘制图例。我也希望图例的出现对用户来说是不明显的。 QML 有什么方法可以做到这一点吗?
【问题讨论】:
您可以尝试创建第二个不可见的 ChartView 并使用 Timer 让 Qt 有时间处理所有内容,然后再将其保存为 PNG。 @m7913d ,这不是太直接的方式,但我会尝试 =) 【参考方案1】:我不确定我是否完全正确。
我的建议是,不要抓取您显示的 Item
,而是它的副本,然后您可以随意修改。复制这里并不意味着您拥有同一个对象两次,但您使用ShaderEffectSource
将其渲染两次。在你把这个ShaderEffectSource
抓到图片之前,你可以添加任何你喜欢的东西。
在我的示例中,我显示了一个简单的Rectangle
,并带有漂亮的渐变。我保存的是相同的Rectangle
,由Text
'我是传奇' 扩展。用户在任何时候都不会在视图中看到此文本。
Rectangle
id: commonView
width: 200
height: 200
gradient: Gradient
GradientStop position: 0; color: 'steelblue'
GradientStop position: 1; color: 'orange'
MouseArea
anchors.fill: parent
// don't grab the rectangle itself.
onClicked: legendView.grabToImage(function(result)
console.log(result.saveToFile("something.png"));
);
ShaderEffectSource
id: legendView
visible: false // Does not need to be shown.
sourceItem: commonView
width: 200
height: 200
Text
anchors
right: parent.right
bottom: parent.bottom
text: 'I am legend'
您可以通过仅激活 ShaderEffectSource
甚至在需要时创建来优化性能。
您可以使用ShaderEffectSource.live
-property 来禁用它的更新。然后使用scheduleUpdate()
触发更新。
这可能看起来像这样:
Rectangle
id: commonView
width: 200
height: 200
gradient: Gradient
GradientStop position: 0; color: 'steelblue'
GradientStop id: gs1; position: 1; color: 'orange'
MouseArea
anchors.fill: parent
onClicked:
gs1.position -= 0.1
legendView.save()
ShaderEffectSource
id: legendView
y: 200
visible: false // Do not render it (will only be rendered when called grapToImage()
sourceItem: commonView
width: 200
height: 200
live: false // Will only be updated, when explicitly called for
function save()
console.log('Schedule Save')
scheduleUpdate() // explicitly update. grabToImage() will force rendering afterwards.
legendView.grabToImage(function(result)
console.log(result.saveToFile("something" +gs1.position.toFixed(1) + ".png"));
)
// Put additional stuff on it.
Text
anchors
right: parent.right
bottom: parent.bottom
text: 'I am legend!'
【讨论】:
这几乎正是 cmets 中的建议,但在我的情况下,这不是一个好的解决方案:由于性能原因,我不能同时更改两个图表系列(动态添加),因此我应该然后在用户想要拍摄快照时创建该图表的副本。无论如何,它需要将图表加倍 - 使用的内存加倍,这可能会成为一个巨大的瓶颈。 您不会将数据翻倍。ShaderEffectSource
仅复制视觉表示。你只有一个ChartView
。也许我需要澄清我的答案来指出这一点。
好吧,我开始明白了,这是一件有趣的事情。但是还有一个问题:我想用ChartView
的方法来绘制图例。但我不知道如何禁用更新commonView
,这样图例就不会出现在上面。当然,如果这根本不可能,我可以像使用 Text
一样切换到自己绘制传奇。
这似乎有问题。我没有安装QtCharts
,但似乎Legend
没有Item
,因此可能不适合作为ShaderEffectSource
的来源。否则,您可以将其转为visible: false
并将我的Text
替换为另一个ShaderEffectSource
为源:chartView.legend
,然后应该在保存的图像上再次可见。你可以试试(也许它是,虽然没有记录,并且是项目)——我不知道它是否会起作用。
哇。我一定会尝试的。 Legend 只是布尔值,但可能里面有一些未记录的图例项以上是关于QML如何绘制不同的grabToImage()的主要内容,如果未能解决你的问题,请参考以下文章
使用grabToImage将QML项目作为图像保存到文件时出错