QML中的图像圆角

QML中的图像圆角,qml,qt5,qtquick2,Qml,Qt5,Qtquick2,令我惊讶的是,Image组件没有radius属性。我试图通过将图像放在圆角的矩形中来模拟圆角,但它不会剪裁圆角 Rectangle { anchors.right: rectContentBg.left anchors.top: rectContentBg.top anchors.margins: 8 radius: 8 width: 64 height: 64 Image { id: imgAuthor

令我惊讶的是,
Image
组件没有
radius
属性。我试图通过将图像放在圆角的
矩形中来模拟圆角,但它不会剪裁圆角

Rectangle {
    anchors.right: rectContentBg.left
    anchors.top: rectContentBg.top
    anchors.margins: 8

    radius: 8

    width: 64
    height: 64

    Image {
        id: imgAuthor

        opacity: 1
        smooth: false

        anchors.fill: parent

        source: "qrc:/res/sample_avatar.jpg"
    }
}

如何正确创建圆角图像?

QML目前仅支持矩形剪裁,但您可能希望查看qt components项目中的DeclarativeSkedimage:


当您的背景为纯色或从不移动图像时,制作圆角的一种快速方法是将您的
图像
与另一个仅绘制角的图像(或a)重叠

Rectangle {
    anchors.right: rectContentBg.left
    anchors.top: rectContentBg.top
    anchors.margins: 8

    radius: 8

    width: 64
    height: 64

    Image {
        id: imgAuthor

        opacity: 1
        smooth: false

        anchors.fill: parent

        source: "qrc:/res/sample_avatar.jpg"
    }
}
如果这不是一个选项,但您使用的是OpenGL,那么另一种方法是通过像素着色器对图像应用遮罩。有关在Qt4上工作的插件,请参阅


最后,还可以编写一个预处理图像以使角变圆的程序。

如果您有单色背景,您可以在顶部绘制圆角矩形的边框

Image{
    id:img
}
Rectangle { // rounded corners for img
    anchors.fill: img
    color: "transparent"
    border.color: "blue" // color of background
    border.width: 4
    radius: 4
}

这个代码会帮助你

Rectangle {
    width: 200
    height: 200

    color: "transparent"

    //this Rectangle is needed to keep the source image's fillMode
    Rectangle {
        id: imageSource

        anchors.fill: parent
        Image {
            anchors.fill: parent
            source: "your_image_file_path"

            fillMode: Image.PreserveAspectCrop
        }
        visible: false

        layer.enabled: true
    }

    Rectangle {
        id: maskLayer
        anchors.fill: parent
        radius: parent.width / 2

        color: "red"

        border.color: "black"

        layer.enabled: true
        layer.samplerName: "maskSource"
        layer.effect: ShaderEffect {

            property var colorSource: imageSource
            fragmentShader: "
                uniform lowp sampler2D colorSource;
                uniform lowp sampler2D maskSource;
                uniform lowp float qt_Opacity;
                varying highp vec2 qt_TexCoord0;
                void main() {
                    gl_FragColor =
                        texture2D(colorSource, qt_TexCoord0)
                        * texture2D(maskSource, qt_TexCoord0).a
                        * qt_Opacity;
                }
            "
        }

    }

    // only draw border line
    Rectangle {
        anchors.fill: parent

        radius: parent.width / 2

        border.color: "black"
        border.width: 2

        color: "transparent"
    }
}

得益于
QtGraphicalEffects
模块,自qt5起就有了一个内置的官方解决方案,我很惊讶地发现没有人提供如此简单的解决方案

在其他影响中,
OpacityMask
是用于此目的的类型。这个想法是用一个正确设置了半径的矩形遮罩源图像。下面是最简单的示例,使用:

这个最小代码为正方形图像生成了一个很好的结果,但是 它还通过
adapt
变量考虑非方形图像。通过将标志设置为
false
生成的遮罩将始终是一个圆形,而不管图像大小如何。这是可能的,因为使用了一个外部
,它填充了源代码,并允许根据需要调整真实掩码(内部
矩形
)的大小。若您只是简单地瞄准一个填充源的掩码,而不管它的纵横比如何,显然可以去掉外部的

这是一张可爱的猫图片,它是方形格式(),非方形格式(
adapt:true
center),最后是非方形格式和
adapt:false
):

此解决方案的实现细节与另一个解决方案中基于着色器的答案非常相似(cfr.
OpacityMask
的QML源代码可以找到-
SourceProxy
只返回格式良好的
ShaderEffectSource
以提供效果)

如果您不想依赖
QtGraphicalEffects
模块(实际上,取决于
OpacityMask.qml
的存在),可以使用着色器重新实现效果。除了已经提供的解决方案外,另一种方法是使用和功能。代码如下:

import QtQuick 2.5

Image {
    id: image

    property bool rounded: true
    property bool adapt: true

    layer.enabled: rounded
    layer.effect: ShaderEffect {
        property real adjustX: image.adapt ? Math.max(width / height, 1) : 1
        property real adjustY: image.adapt ? Math.max(1 / (width / height), 1) : 1

        fragmentShader: "
        #ifdef GL_ES
            precision lowp float;
        #endif // GL_ES
        varying highp vec2 qt_TexCoord0;
        uniform highp float qt_Opacity;
        uniform lowp sampler2D source;
        uniform lowp float adjustX;
        uniform lowp float adjustY;

        void main(void) {
            lowp float x, y;
            x = (qt_TexCoord0.x - 0.5) * adjustX;
            y = (qt_TexCoord0.y - 0.5) * adjustY;
            float delta = adjustX != 1.0 ? fwidth(y) / 2.0 : fwidth(x) / 2.0;
            gl_FragColor = texture2D(source, qt_TexCoord0).rgba
                * step(x * x + y * y, 0.25)
                * smoothstep((x * x + y * y) , 0.25 + delta, 0.25)
                * qt_Opacity;
        }"
    }
}


与第一种方法类似,添加了
四舍五入
自适应
属性,以控制上述效果的视觉外观。

我知道我参加派对有点晚,但我是通过谷歌搜索来的,所以我想我会帮助后代:)QtGraphicalEffects OpacityMask应该更简单一些(我对图层效果方法有疑问)


虽然这两个被接受的答案对我来说同样有效(Qt 5.9.3),但当应用于光栅图像时,它们都在角落留下了一些像差(没有SVG)。在所有情况下,对我最有效的是将
OpacityMask
应用于周围的项目,例如,像原始帖子中的矩形

Rectangle {
    id: root;
    anchors.right: rectContentBg.left
    anchors.top: rectContentBg.top
    anchors.margins: 8

    radius: 8

    width: 64
    height: 64

    // apply rounded corners mask
    layer.enabled: true
    layer.effect: OpacityMask {
        maskSource: Rectangle {
            x: root.x; y: root.y
            width: root.width
            height: root.height
            radius: root.radius
        }
    }

    Image {
        id: imgAuthor
        opacity: 1
        smooth: false
        anchors.fill: parent
        source: "qrc:/res/sample_avatar.jpg"
    }
}

他们真的应该做到这一点,而不是他们现在正在做的那些花哨的3D东西:/回答得好,谢谢!我想指出的是,在你的第一种方法中,如果你在一个项目中使用一个矩形,你不需要声明该项目,你可以直接使用矩形,因为矩形继承了该项目。你为什么要包装
矩形
项目
?@Phrogz中,效果是源代码,即使我将
自适应
设置为
我也无法在第一个系列的第三张图片中得到结果。如果你有一张与第一张图片类似的方形图片,那么外部的
项目
根本没有用处。要添加吗,如果你的目标是移动设备,你应该设置它layer.textureSize,这样你就可以保持完整的分辨率,只要半径大于border.Width,它就可以工作。虽然这个答案可行,但我偶尔会看到一些渲染人工制品,这意味着它本身看起来不太专业。幸运的是,这些小故障只是垂直线(在win7上),所以两个放置良好的矩形可以清理它。
Rectangle {
    id: root;
    anchors.right: rectContentBg.left
    anchors.top: rectContentBg.top
    anchors.margins: 8

    radius: 8

    width: 64
    height: 64

    // apply rounded corners mask
    layer.enabled: true
    layer.effect: OpacityMask {
        maskSource: Rectangle {
            x: root.x; y: root.y
            width: root.width
            height: root.height
            radius: root.radius
        }
    }

    Image {
        id: imgAuthor
        opacity: 1
        smooth: false
        anchors.fill: parent
        source: "qrc:/res/sample_avatar.jpg"
    }
}