您当前的位置: 首页 > 

龚建波

暂无认证

  • 5浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

解决QML中clip对圆角无效的问题

龚建波 发布时间:2021-03-07 01:50:19 ,浏览量:5

问题

根据 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 效果产生影响,因为里面的色块还是完整的方形。 

解决方案 1.使用 OpacityMask 遮罩

效果图:

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
                }
            }
        }
    }
}

 

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.0684s