问题
根据 QML Item 类型 clip 属性的文档:
https://doc.qt.io/qt-5/qml-qtquick-item.html#clip-prop
https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html#clipping
可以看到,他描述的是根据 Item 的矩形边框剪切,没有对圆角或其他异形进行处理。
实测默认效果:
Rectangle{ anchors.centerIn: parent radius: 20 clip: true width: 200 height: 200 color: "green" Rectangle{ width: 100 height: 100 color: "red" } }
运行上面的代码可以看到外层的 radius 并不会对 clip 效果产生影响,因为里面的色块还是完整的方形。
效果图:
import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.0 Window { width: 640 height: 480 visible: true title: qsTr("龚建波 1992") Rectangle{ anchors.centerIn: parent width: 200 height: 200 color: "green" layer.enabled: true layer.effect: OpacityMask{ maskSource: Rectangle{ width: 200 height: 200 radius: 20 } } Rectangle{ width: 100 height: 100 color: "red" } } }
或者这样写:
import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.0 Window { width: 640 height: 480 visible: true title: qsTr("龚建波 1992") Rectangle{ id: rect visible: false width: 200 height: 200 color: "green" Rectangle{ width: 100 height: 100 color: "red" } } OpacityMask{ anchors.centerIn: parent width: 200 height: 200 source: rect maskSource: Rectangle{ width: 200 height: 200 radius: 20 } } }2.使用 ShaderEffect 写着色器
OpacityMask 也是用 ShaderEffect 实现的,自己写着色器要注意的是对不同着色器版本进行兼容处理,我这里只写了个简单的没处理版本问题:
import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.0 Window { width: 640 height: 480 visible: true title: qsTr("龚建波 1992") color: "gray" Rectangle{ id: rect visible: false radius: 20 width: 200 height: 200 color: "green" Rectangle{ width: 100 height: 100 color: "red" } } ShaderEffect{ anchors.centerIn: parent width: 200 height: 200 property var source: ShaderEffectSource{ sourceItem: rect } property var mask: ShaderEffectSource{ sourceItem: Rectangle{ width: 200 height: 200 radius: 20 } } vertexShader: " uniform highp mat4 qt_Matrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 coord; void main() { coord = qt_MultiTexCoord0; gl_Position = qt_Matrix * qt_Vertex; }" fragmentShader: " varying highp vec2 coord; uniform lowp float qt_Opacity; uniform sampler2D source; uniform sampler2D mask; void main() { gl_FragColor = texture2D(source, coord) * texture2D(mask, coord) * qt_Opacity; }" } }3.其他
文档提到的 QSGNode 太麻烦,忽略。
拓展机智你可能已经发现了,遮罩不仅能实现四个圆角的 clip,也能实现自己想要的圆角效果(QML 默认四个圆角是统一设置的):
import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.0 Window { width: 640 height: 480 visible: true title: qsTr("龚建波 1992") Rectangle{ anchors.centerIn: parent width: 200 height: 200 color: "green" layer.enabled: true layer.effect: OpacityMask{ maskSource: Rectangle{ width: 200 height: 200 radius: 50 //左侧 Rectangle{ width: 60 height: 200 } //右上角 Rectangle{ width: 60 height: 60 radius: 20 anchors.right: parent.right } } } } }