如何在Qt Quick中保存已应用OpacityMask效果的界面截图?
Qt Quick 调用grabToImage保存界面时OpacityMask效果丢失问题
问题描述
项目开发中需要保存渲染界面的缩略图,要求与实际显示效果完全一致,包含已生效的OpacityMask效果,但实际操作后生成的缩略图始终没有应用遮罩效果。
实际界面显示效果如下:
保存生成的图片效果如下:
问题复现代码
import QtQuick 2.15 import QtGraphicalEffects 1.12 import QtQuick.Layouts 1.2 import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.1 ApplicationWindow { id: root width: 640 property bool round: true toolBar: ToolBar { RowLayout { anchors.fill: parent anchors.margins: spacing CheckBox { id: roundCheckBox text: "Round" Component.onCompleted: checked = round onCheckedChanged: round = checked; } Item { Layout.fillWidth: true } } } Rectangle { height: 640 width: 640 Rectangle { id: frame anchors.fill: parent focus: true color: "black" Image { id: background source: "background.jpg" anchors.fill: parent } Rectangle { anchors.centerIn: parent width: parent.width/2 height: parent.height/2 color: "red" } layer.enabled: round layer.effect: OpacityMask { anchors.fill: parent source: frame maskSource: Rectangle { width: frame.width height: frame.height radius: frame.width/2 } } Keys.onReturnPressed: frame.grabToImage( function(result) { result.saveToFile("example.jpg") }, Qt.size(320, 320) ) } } }
解决方案
问题核心原因是grabToImage默认抓取的是Item自身的原始绘制内容,不会包含该Item绑定的layer.effect特效结果:特效是在离屏渲染的独立layer图层上生效的,需要调整抓取逻辑即可解决:
方法1:直接抓取layer的渲染结果
仅修改触发保存的代码,直接对layer对象调用抓取方法:
Keys.onReturnPressed: frame.layer.grabToImage( function(result) { result.saveToFile("example.jpg") }, Qt.size(320, 320) )
方法2:调整层级结构,抓取特效挂载的父级节点
也可以把OpacityMask挂载到frame的父容器上,再抓取父容器的内容,同样可以拿到带特效的结果:
// 仅需修改frame外层容器相关代码即可 Rectangle { id: frameParent height: 640 width: 640 layer.enabled: round layer.effect: OpacityMask { anchors.fill: parent source: frameParent maskSource: Rectangle { width: frameParent.width height: frameParent.height radius: frameParent.width/2 } } Rectangle { id: frame anchors.fill: parent focus: true color: "black" Image { id: background source: "background.jpg" anchors.fill: parent } Rectangle { anchors.centerIn: parent width: parent.width/2 height: parent.height/2 color: "red" } // 抓取挂载了特效的父容器 Keys.onReturnPressed: frameParent.grabToImage( function(result) { result.saveToFile("example.jpg") }, Qt.size(320, 320) ) } }
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

