41

驚いたことに、Imageコンポーネントにはradiusプロパティがありません。画像を rounded に入れて丸みを帯びた角をエミュレートしようとしましたが、角が切り取られ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"
    }
}

角を丸くした画像を適切に作成するにはどうすればよいですか?

4

8 に答える 8

57

このモジュールのおかげで、組み込みの公式ソリューションが Qt 5 の時点で存在しQtGraphicalEffectsますが、誰もそのような単純なソリューションを提供していないことに非常に驚いています。Qt 6.x をターゲットにしている場合QtGraphicalEffectsは、残念ながら非推奨です。回答の 2 番目の部分にジャンプして、QtGraphicalEffects.

QtGraphicalEffects解決

他の効果の中にOpacityMaskは、この目的のために悪用されるタイプがあります。アイデアは、正しく設定されImageた でソースをマスクすることです。レイヤリングを使用した最も単純な例を次に示します。Rectangleradius

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(中央)、最後に非正方形フォーマットadapt: false()のかわいい猫の画像です。

ここに画像の説明を入力

このソリューションの実装の詳細は、他の素晴らしい回答のシェーダーベースの回答と非常によく似ています(cfr。そのための QML ソースコードはここOpacityMaskにあります-効果をフィードするために整形式を返すだけです)。SourceProxyShaderEffectSource

非依存ソリューション

モジュールに依存したくない (または依存できない) 場合は (つまり、実際の存在に依存します)、シェーダーを使用して効果を再実装できます。既に提供されているソリューションとは別に、別のアプローチは、および関数を使用することです。コードは次のとおりです。QtGraphicalEffectsOpacityMask.qmlstepsmoothstepfwidth

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上記adaptで説明したように、効果の視覚的な外観を制御するためにプロパティが追加されます。

于 2015-09-22T07:24:47.263 に答える
7

背景が単色の場合、または画像をまったく動かさない場合、角を丸くする簡単な方法は、角だけを描画するImage別の背景 (または ) と重ねることです。BorderImage

これがオプションではなく、OpenGL を使用している場合は、別の方法として、ピクセル シェーダーを介して画像にマスクを適用します。Qt 4 上で動作するプラグインについては、http://blog.qt.digia.com/blog/2011/05/03/qml-shadereffectitem-on-qgraphicsview/を参照してください。

最後に、QDeclarativeImageProvider画像を前処理して角を丸くする を作成することもできます。

于 2011-05-23T08:31:32.560 に答える
6

単色の背景の場合は、角丸長方形の境界線を上にして描画できます。

Image{
    id:img
}
Rectangle { // rounded corners for img
    anchors.fill: img
    color: "transparent"
    border.color: "blue" // color of background
    border.width: 4
    radius: 4
}
于 2012-01-25T18:12:05.807 に答える
4

QML は現在、長方形のクリッピングのみをサポートしていますが、qt-components プロジェクトの DeclarativeMaskedImage を参照してください。

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

于 2011-05-23T06:14:25.963 に答える
4

私はパーティーに少し遅れていることを知っていますが、グーグルでここにたどり着いたので、将来の世代を助けると思いました:) QtGraphicalEffects OpacityMask はこれをもう少し簡単に行う必要があります (レイヤー効果アプローチに問題がありました)

Image {
    id: imgAuthor

    width: 64
    height: 64

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

    visible: false // this is needed or the corners of the image will be visible underneath the opacity mask
}

OpacityMask {
    anchors.fill: imgAuthor
    source: imgAuthor
    maskSource: Rectangle {
        width: imgAuthor.width
        height: imgAuthor.height
        radius: 8
        visible: false // this also needs to be invisible or it will cover up the image
    }
}
于 2017-06-09T15:58:24.433 に答える