Qt6 MultiEffect蒙版问题:自定义ProgressBar无法正确适配圆角蒙版
Qt Quick自定义ProgressBar蒙版适配问题解决方案
我想要自定义一个ProgressBar,目标外观如下:
需要裁剪内部的「浅橙色」矩形,使其适配橙色圆角背景。我使用MultiEffect来实现,但无法正确设置蒙版。背景Rectangle的radius为70,当前内容项的MultiEffect代码如下:
Item { id: contentRect Rectangle { id: progressRectangle // z: parent.z + 1 color: DefaultStyle.grey_0 width: mainItem.barWidth height: parent.height opacity: 0.5 visible: false } MultiEffect { anchors.fill: progressRectangle source: progressRectangle maskThresholdMin: 0.5 maskSpreadAtMin: 1.0 maskEnabled: true maskSource: mask // opacity: 0.5 } Item { id: mask layer.enabled: true layer.smooth: true visible: false width: contentRect.width height: contentRect.height Rectangle { width: contentRect.width height: contentRect.height radius: Math.round(70 * DefaultStyle.dp) color: "black" } } ... }
已确认蒙版尺寸正确:
但根据文档说明:
如果maskSource与source尺寸不同,maskSource图像会被拉伸以匹配source尺寸。
由于内部矩形的尺寸会随进度条的百分比变化,导致蒙版随内部Rectangle尺寸变化而变形,效果如下:

不想使用Qt5Compatibility API调用Qt5 GraphicalEffects API,以下是解决方案:
核心思路
问题根源是蒙版被强制拉伸适配进度条的动态宽度,导致圆角形状变形。解决关键是让蒙版尺寸始终匹配背景容器的固定尺寸,而非进度条的动态宽度。
方法1:调整MultiEffect的适配逻辑
将MultiEffect的尺寸绑定到背景容器,通过sourceRect控制仅显示进度条的有效区域:
Item { id: contentRect // 绑定到背景容器的固定尺寸 width: mainItem.backgroundWidth height: mainItem.backgroundHeight Rectangle { id: progressRectangle color: DefaultStyle.grey_0 width: mainItem.barWidth // 随进度变化的宽度 height: parent.height opacity: 0.5 visible: false } MultiEffect { anchors.fill: contentRect // 匹配背景容器尺寸 source: progressRectangle // 仅截取进度条的有效宽度区域 sourceRect: Qt.rect(0, 0, mainItem.barWidth, contentRect.height) maskThresholdMin: 0.5 maskSpreadAtMin: 1.0 maskEnabled: true maskSource: mask } Item { id: mask layer.enabled: true layer.smooth: true visible: false width: contentRect.width // 保持背景容器尺寸 height: contentRect.height Rectangle { width: parent.width height: parent.height radius: Math.round(70 * DefaultStyle.dp) color: "black" } } }
方法2:使用原生layer.mask替代MultiEffect
Qt Quick的layer.mask可以直接为Item添加蒙版,逻辑更直观,无需额外的MultiEffect:
Item { id: contentRect width: mainItem.backgroundWidth height: mainItem.backgroundHeight Rectangle { id: progressRectangle color: DefaultStyle.grey_0 width: mainItem.barWidth height: parent.height opacity: 0.5 // 启用layer并设置蒙版 layer.enabled: true layer.mask: Rectangle { width: contentRect.width // 匹配背景容器尺寸 height: contentRect.height radius: Math.round(70 * DefaultStyle.dp) color: "white" // 白色区域保留,透明区域裁剪 } } }
效果说明
两种方法都能保证蒙版的圆角形状始终与背景一致,进度条宽度变化时,只会裁剪超出圆角的部分,不会导致蒙版变形。其中方法2更简洁,推荐优先使用。
内容的提问来源于stack exchange,提问作者gra
相关产品推荐
相关产品推荐

