QML中的图像圆角

时间:2011-05-22 20:58:51

标签: qml qt5 qtquick2

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

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

如何正确创建圆角图像?

7 个答案:

答案 0 :(得分:40)

由于QtGraphicalEffects模块,Qt 5中存在内置的官方解决方案,我很惊讶地发现没有人提供这样简单的解决方案。

在其他效果中,OpacityMask是为此目的而被利用的类型。我们的想法是使用具有正确设置Image的{​​{1}}来屏蔽来源Rectangle。以下是使用layering

的最简单示例
radius

这个最小代码为方形图像产生了很好的效果,但是 它还通过Image { id: img property bool rounded: true property bool adapt: true layer.enabled: rounded layer.effect: OpacityMask { maskSource: Item { width: img.width height: img.height Rectangle { anchors.centerIn: parent width: img.adapt ? img.width : Math.min(img.width, img.height) height: img.adapt ? img.height : width radius: Math.min(width, height) } } } } 变量考虑非方形图像。通过将标志设置为adapt,无论图像大小如何,生成的蒙版始终为圆形。这是可能的,因为使用外部false填充源并允许真正的掩码(内部Item)在适当的大小。 你可以明显地摆脱外部Rectangle,如果你只是针对一个填充源的面具,无论其纵横比

这是一个可爱的猫图像,方形格式(),非方格式Item中心),最后是非方格式和adapt: true):

enter image description here

此解决方案的实现细节与其他nice answer中基于着色器的答案的实现细节非常相似(cfr。adapt: false的{​​{1}}的QML源代码here - OpacityMask只返回格式正确的SourceProxy来提供效果。)

如果您不想依赖ShaderEffectSource模块(嗯,实际存在QtGraphicalEffects),您可以使用着色器重新实现效果。除了已经提供的解决方案,另一种方法是使用stepsmoothstepfwidth函数。这是代码:

OpacityMask.qml

enter image description here

与第一种方法类似,添加了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; }" } } rounded属性来控制效果的视觉外观,如上所述。

答案 1 :(得分:7)

当您的背景为纯色或者您从未移动图片时,快速制作圆角的方法是将您的Image与另一个(或BorderImage)重叠只画出角落。

如果这不是一个选项,但您使用的是OpenGL,那么另一种方法是通过像素着色器将遮罩应用于图像。有关在Qt 4之上工作的插件,请参阅http://blog.qt.digia.com/blog/2011/05/03/qml-shadereffectitem-on-qgraphicsview/

最后,还可以编写一个预处理图像的QDeclarativeImageProvider来使角落四舍五入。

答案 2 :(得分:6)

This code would help you

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

答案 3 :(得分:5)

QML目前仅支持矩形剪切,但您可能需要查看qt-components项目中的DeclarativeMaskedImage:

http://qt.gitorious.org/qt-components/qt-components/blobs/master/src/symbian/sdeclarativemaskedimage.h

答案 4 :(得分:5)

如果您有单色背景,则可以使用顶部圆角矩形的边框进行绘制。

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

答案 5 :(得分:4)

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

Repo.insert_all! MyApp.UserRole, [%{user_id: 1, role_id: 1},
                                  %{user_id: 2, role_id: 1},
                                  %{user_id: 2, role_id: 2}]

答案 6 :(得分:2)

虽然接受的答案和the one from @fury同样适用于我(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"
    }
}