Image with radius in QML
-
-
It is possible with the "QML Shaders":http://labs.qt.nokia.com/2011/05/03/qml-shadereffectitem-on-qgraphicsview/ plugin.
@
import QtQuick 1.0
import Qt.labs.shaders 1.0Item {
width: 600
height: 300Rectangle { id: mask anchors.centerIn: parent width: 400 height: 200 radius: 20 } Image { id: image anchors.fill: mask source: "test.jpg" } ShaderEffectSource { id: sourceMask smooth: true hideSource: true sourceItem: mask } ShaderEffectSource { id: sourceImage hideSource: true sourceItem: image } ShaderEffectItem { id: maskEffect anchors.fill: mask property variant sourceTexture: sourceImage property variant maskTexture: sourceMask vertexShader: " uniform highp mat4 qt_ModelViewProjectionMatrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 qt_TexCoord; void main(void) { qt_TexCoord = qt_MultiTexCoord0; gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex; } " fragmentShader: " uniform lowp sampler2D sourceTexture; uniform lowp sampler2D maskTexture; varying highp vec2 qt_TexCoord; void main (void) { vec4 c = texture2D(sourceTexture, qt_TexCoord); vec4 m = texture2D(maskTexture, qt_TexCoord); gl_FragColor = vec4(c.rgb, m.a); } " }
}
@ -
Interesting approach, but to be honest, I don't think this kind of code is really what we should strive for in QML. It is not really readable, and also not really declarative.
I'm sure your code produces a faster UI, but for simplicity, I would go for something like this:
@
import QtQuick 1.0
Item {
width: 600
height: 300Rectangle { id: mask anchors.centerIn: parent width: 400 height: 200 radius: 20 Image { id: image anchors.fill: parent source: "test.jpg" } }
}
@That should work as well, and is, IMHO, clearer to read.
-
At the beginning I tried with that code but it didn't work. The image is set over the rectangle hidding the round corners. I will try again but I think it doesn't work.
If I nest, in the opposite way, the Rectangle inside the Image, it shows the border over the image but it doesn't hide the corners either.
-
Sorry, you probably need to enable clipping.
@
import QtQuick 1.0
Item {
width: 600
height: 300Rectangle { id: mask anchors.centerIn: parent width: 400 height: 200 radius: 20 clip: true Image { id: image anchors.fill: parent source: "test.jpg" } }
}
@Edit:
On the other hand: the docs to state:
[quote]Non-rectangular clipping regions are not supported for performance reasons.[/quote]So, perhaps a rounded rect will not clip properly after all.
-
Hello,
I am trying the shader solution, but it gives me this error at runtime:
@
QGLShaderProgram::addShader: Program and shader are not associated with same context.
QGLShaderProgram::addShader: Program and shader are not associated with same context.
QGLShader::link: "Link Error: Vertex shader is missing.
Link Error: Fragment shader is missing.
"
ShaderEffectItem: Shader compilation failed:
"Link Error: Vertex shader is missing.
Link Error: Fragment shader is missing.
"
QGLShader::link: "Link Error: Vertex shader is missing.
Link Error: Fragment shader is missing.
"
QGLShaderProgram::uniformLocation( qt_ModelViewProjectionMatrix ): shader program is not linked
QGLShaderProgram::addShader: Program and shader are not associated with same context.
QGLShaderProgram::addShader: Program and shader are not associated with same context.
QGLShader::link: "Link Error: Vertex shader is missing.
@And this is the code I have used:
@
Item {
width: 200
height: 200
//radius: 20
//border.width: 6
//border.color: "#ffea00"signal tapOnProfilePicture property alias profileImageSource: image.source Rectangle { id: mask anchors.centerIn: parent width: 200 height: 200 radius: 20 } Image { id: image anchors.fill: mask source: "qrc:/images/profile-mask.png" } ShaderEffectSource { id: sourceMask smooth: true hideSource: true sourceItem: mask } ShaderEffectSource { id: sourceImage hideSource: true sourceItem: image } ShaderEffectItem { id: maskEffect anchors.fill: mask property variant sourceTexture: sourceImage property variant maskTexture: sourceMask vertexShader: " uniform highp mat4 qt_ModelViewProjectionMatrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 qt_TexCoord; void main(void) { qt_TexCoord = qt_MultiTexCoord0; gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex; } " fragmentShader: " uniform lowp sampler2D sourceTexture; uniform lowp sampler2D maskTexture; varying highp vec2 qt_TexCoord; void main (void) { highp vec4 c = texture2D(sourceTexture, qt_TexCoord); highp vec4 m = texture2D(maskTexture, qt_TexCoord); gl_FragColor = vec4(c.rgb, m.a); } " } MouseArea { z: 10 anchors.fill: parent onClicked: { tapOnProfilePicture() } }
}
@Notice I have added highp to vec4 declarations to avoid other errors.
-
Hi you can use an "OpacityMask":http://qt-project.org/doc/qt-5/qml-qtgraphicaleffects-opacitymask.html. Use a rounded image and mask your image with it.
-
[quote author="Brexis" date="1397022356"]Hi you can use an "OpacityMask":http://qt-project.org/doc/qt-5/qml-qtgraphicaleffects-opacitymask.html. Use a rounded image and mask your image with it.[/quote]
Yes, that is a good solution!