Qt Quick中Rectangle添加DropShadow后clip失效导致Ripple效果溢出
Qt Quick DropShadow与Ripple效果冲突解决方案
问题根因
当DropShadow的source属性绑定到某一组件时,Qt Quick会强制为该组件开启离屏渲染(自动设置layer.enabled: true)。Qt 5.x版本中,开启离屏渲染的组件自带的clip属性对圆角边界的裁剪存在兼容性缺陷,直接导致裁剪失效,Ripple效果就会溢出矩形边界。
你之前为Ripple单独添加OpacityMask不生效,是因为需要裁剪的是Rectangle内部所有超出边界的内容,裁剪对象应为父级Rectangle,而非单个Ripple组件。
解决方案
方案1:调整阴影作用对象(优先推荐,性能损耗更低)
给带Ripple的Rectangle外层套一层空的Item容器,将DropShadow的source绑定到这个外层容器,这样内层Rectangle的clip属性不会受离屏渲染影响,裁剪逻辑可以正常工作。
import QtQuick 2.12 import QtGraphicalEffects 1.12 import QtQuick.Controls.Material.impl 2.12 Item{ width: 400 height: 100 // 阴影作用于外层容器,不影响内层矩形的clip逻辑 DropShadow { anchors.fill: shadowContainer horizontalOffset: 0 verticalOffset: 0 radius: 12.0 samples: 17 color: "#50000000" source: shadowContainer } // 新增外层容器,仅作为阴影的源对象 Item { id: shadowContainer anchors.fill: parent anchors.margins: 8 Rectangle{ id:itemRect anchors.fill: parent border.width: 1 radius: 5 clip: true // 此处clip可正常生效 MouseArea{ id: button anchors.fill: parent onPressed: { ripple.x=mouseX-(ripple.width/2); ripple.y=mouseY-(ripple.height/2); } Ripple { id: ripple clipRadius: 2 width: itemRect.width*2 height: itemRect.height*2 pressed: button.pressed active: false color: "#10000000" } } } } }
方案2:手动添加OpacityMask替代自带clip
如果场景不允许新增嵌套组件,可以为Rectangle手动配置离屏渲染的OpacityMask,手动实现圆角边界裁剪,哪怕开启离屏渲染也能正常裁剪内容。
import QtQuick 2.12 import QtGraphicalEffects 1.12 import QtQuick.Controls.Material.impl 2.12 Item{ width: 400 height: 100 DropShadow { anchors.fill: itemRect horizontalOffset: 0 verticalOffset: 0 radius: 12.0 samples: 17 color: "#50000000" source: itemRect } Rectangle{ id:itemRect anchors.fill: parent; anchors.margins: 8; border.width: 1 radius: 5; // 去掉原生clip,用layer的OpacityMask实现圆角裁剪 layer.enabled: true layer.effect: OpacityMask { maskSource: Rectangle { width: itemRect.width height: itemRect.height radius: itemRect.radius } } MouseArea{ id: button anchors.fill: parent onPressed: { ripple.x=mouseX-(ripple.width/2); ripple.y=mouseY-(ripple.height/2); } Ripple { id: ripple clipRadius: 2 width: itemRect.width*2 height: itemRect.height*2 pressed: button.pressed active: false color: "#10000000" } } } }
内容的提问来源于stack exchange,提问作者mmjvox
相关产品推荐
相关产品推荐

