Qml semi transparent blur overlay rectangle - qt

I am trying to create a semi transparent blur rectangle which is overlay on another rectangle in Qt Quick Qml.
Rectangle {
id: mainRect
anchors.fill: parent
color: "transparent"
// This is my background rect
Rectangle {
id: backgroundRect
anchors.fill: parent
color: "blue"
}
// This is my semi-transparent-blur overlay rect
Rectangle {
id: blurRect
anchors.fill: parent
color: "#000000"
opacity: 0.5
}
// I did try these but I see black rectangle
ShaderEffectSource {
id: effectSource
sourceItem: blurRect
anchors.fill: blurRect
}
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
I see an black rectangle when I run this.
How should I create a semi transparent blur overlay Rectangle/Item.

Here is how I have done it in the past without layers or manually using ShaderEffectSource objects:
Image {
id: backgroundImage
source: "some_image.png"
}
Item {
id: blurRect
anchors.fill: parent
FastBlur {
anchors.fill: parent
source: backgroundImage
radius: 64
}
Rectangle {
anchors.fill: parent
color: "red"
opacity: 0.5
}
}

Look at this code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: backgroundRect
anchors.fill: parent
color: "blue"
}
Rectangle
{
id:blureRect
anchors.fill: parent
layer.smooth: true
layer.enabled: true
opacity: 0.5
layer.effect: ShaderEffect {
id: effectSource
anchors.fill: parent
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
}
}
output:
before blur rect :
after blur rect :
If I use an image in the background you can see blur rect better :
Image {
id: img
anchors.fill: parent
source: "/images/monkey_off_128x128.png"
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
}
Rectangle
{
id:blureRect
anchors.fill: parent
layer.smooth: true
layer.enabled: true
opacity: 0.5
layer.effect: ShaderEffect {
id: effectSource
anchors.fill: parent
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
}

Related

Qt6.3 QML FastBlur [duplicate]

I am trying to create a semi transparent blur rectangle which is overlay on another rectangle in Qt Quick Qml.
Rectangle {
id: mainRect
anchors.fill: parent
color: "transparent"
// This is my background rect
Rectangle {
id: backgroundRect
anchors.fill: parent
color: "blue"
}
// This is my semi-transparent-blur overlay rect
Rectangle {
id: blurRect
anchors.fill: parent
color: "#000000"
opacity: 0.5
}
// I did try these but I see black rectangle
ShaderEffectSource {
id: effectSource
sourceItem: blurRect
anchors.fill: blurRect
}
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
I see an black rectangle when I run this.
How should I create a semi transparent blur overlay Rectangle/Item.
Here is how I have done it in the past without layers or manually using ShaderEffectSource objects:
Image {
id: backgroundImage
source: "some_image.png"
}
Item {
id: blurRect
anchors.fill: parent
FastBlur {
anchors.fill: parent
source: backgroundImage
radius: 64
}
Rectangle {
anchors.fill: parent
color: "red"
opacity: 0.5
}
}
Look at this code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: backgroundRect
anchors.fill: parent
color: "blue"
}
Rectangle
{
id:blureRect
anchors.fill: parent
layer.smooth: true
layer.enabled: true
opacity: 0.5
layer.effect: ShaderEffect {
id: effectSource
anchors.fill: parent
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
}
}
output:
before blur rect :
after blur rect :
If I use an image in the background you can see blur rect better :
Image {
id: img
anchors.fill: parent
source: "/images/monkey_off_128x128.png"
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
}
Rectangle
{
id:blureRect
anchors.fill: parent
layer.smooth: true
layer.enabled: true
opacity: 0.5
layer.effect: ShaderEffect {
id: effectSource
anchors.fill: parent
FastBlur{
id: blur
anchors.fill: effectSource
source: effectSource
radius: 32
}
}
}

LinearGradient inside Rectangle is displaying blurred white borders

I am using LinearGradient as background for rectangle, but the left and right borders of the rectangle are a little bit white and blurred. How can I avoid this situation?
I have tried to set below properties on the Rectangle but it didn't work.
clip: true
smooth: true
antialiasing: true
Here is my code:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtGraphicalEffects 1.15
Window {
width: 640
height: 480
visible: true
Rectangle {
anchors.fill: parent
color: "#4f4444"
}
Rectangle {
id: root
anchors.centerIn: parent
width: 355
height: 90
radius: 50
LinearGradient {
anchors.fill: parent
source: ShaderEffectSource {
sourceItem: root
recursive: true
}
start: Qt.point(0, 0)
end: Qt.point(parent.width, 0)
gradient: Gradient {
GradientStop { position: 0.0; color: "#2a3254" }
GradientStop { position: 1.0; color: "#0e1c57" }
}
}
Text {
anchors.centerIn: parent
text: "Click me!"
color: "white"
}
}
}
The problem is that it is smoothing the edges of the shape to blend with the Rectangle that contains the gradient (root). If you change that Rectangle's color to match what is drawn behind it, you won't see those edges anymore.
Rectangle {
id: bground
anchors.fill: parent
color: "#4f4444"
}
Rectangle {
id: root
color: bground.color // Match the background's color
LinearGradient { ... }
}

How to use ColorOverlay on item in layout?

I have a RowLayout with some items
RowLayout {
anchors.fill: parent
anchors.leftMargin: 3
Image {
id: icon
source: imgSource
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
}
Text {
id: caption
height: parent.height
fontSizeMode: Text.Fit
font.pointSize: textSize
verticalAlignment: Text.AlignVCenter
text: captionText
color: "white"
}
}
and I want to apply ColorOverlay on Image inside this layout:
ColorOverlay {
id: overlay
anchors.fill: icon
source: icon
color: "#ff0000ff"
}
But if I put ColorOverlay outside of the layout, then I can't use anchors.fill: icon. And if I make it a child
Image {
id: icon
source: imgSource
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
ColorOverlay {
id: overlay
anchors.fill: icon
source: icon
color: "#ff0000ff"
}
}
it seems to work but I get warnings in console ShaderEffectSource: 'recursive' must be set to true when rendering recursively.
To set an effect on an Item you can use Item layers, in your case it would be :
Image {
source: imgSource
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
layer {
enabled: true
effect: ColorOverlay {
color: "#ff0000ff"
}
}
}
Note that you don't have to set the source or the size of the effect, it is done automatically.
You could "pack" the image with its overlay in some custom item, for example:
MyImage.qml
import QtQuick 2.11
import QtGraphicalEffects 1.0
Item {
Image {
id: icon
source: "http://placeimg.com/200/200/any"
visible: false
}
ColorOverlay {
anchors.fill: icon
source: icon
color: "#8000ff00"
}
}
and so use it instead of image:
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Layouts 1.11
Window {
visible: true
width: 640
height: 480
RowLayout {
width: parent.width
anchors.leftMargin: 3
MyImage {
Layout.preferredWidth: parent.width / 2
}
Text {
id: caption
fontSizeMode: Text.Fit
font.pointSize: 14
text: "Some caption here"
Layout.preferredWidth: parent.width / 2
}
}
}

Qt Quick adding gradient frame around Image

I am working on application using Qt 5.4.1 and its Qt Quick module. I load some .svg pictures from /images directory and then show them in ListView, which works ok. But, how do I add shadow gradient around every loaded .svg image? Here is MWE:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import Qt.labs.folderlistmodel 2.1
Rectangle
{
id: ueMainWindow
visible: true
width: 800
height: 1280
color: "black"
property string ueRootDirectory:"/images"
property real ueImagesLoadProgress;
property bool ueImageLoading;
Rectangle
{
id: ueContainerThumbnails
antialiasing: true
color: "black"
anchors.bottom: ueMainWindow.bottom
width: ueMainWindow.width
height: 256
gradient: Gradient
{
GradientStop { position: 0.0; color: "black" }
GradientStop { position: 1.0; color: "grey" }
}
Text
{
id: ueTextImageName
antialiasing: true
color: "white"
anchors.horizontalCenter: ueContainerThumbnails.horizontalCenter
text: qsTr("TestApp")
}
ListView
{
id: ueViewThumbnails
antialiasing: true
orientation: ListView.Horizontal
anchors
{
topMargin: parent.height-(parent.height-50)
fill: parent
}
FolderListModel
{
id: ueModelImages
folder: "file://"+ueRootDirectory
nameFilters: ["*.svg"]
}
Component
{
id: ueDelegateImage
Image
{
id: ueImage
source: ueModelImages.folder + "/" + fileName
antialiasing: true
asynchronous: true
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
width: 192
height: 192
fillMode: Image.PreserveAspectFit
}
}
focus: true
spacing: 10
leftMargin: 10
rightMargin: 35
visible: ueModelImages.status==FolderListModel.Ready
model: ueModelImages
delegate: ueDelegateImage
}
}
}
Well, you should put that gradient into your delegate somehow. You can either:
create an empty Item and put the Rectangle and Image inside it
example:
Component {
id: ueDelegateImage
Item { // container
Rectangle {
// gradient rectangle
}
Image {
// image
}
}
}
or put the Image inside the Rectangle
example:
Component {
id: ueDelegateImage
Rectangle {
// gradient rectangle acts as a container
Image {
// image
}
}
}
In both cases stacking order will draw the gradient rectangle behind the image. A delegate should only have one root element, but is not limited to just one element, you can nest as many as you like.

QML: How to make nice transition effect between image sources (one fades into the other)?

I wonder how to make smooth transitions betwen image sources in QML, I try
import QtQuick 1.1
Image {
id: rect
source: "quit.png"
smooth: true
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; source :"quit2.png" }
}
transitions: Transition {
NumberAnimation { properties: "scale, source"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
But It does not work on source as a transition just as final state change.. so I wonder how to make one image source fade into andothe and back?
You want the first image to fade out into the other? How about if you place two Image objects on top of each other, then animate the opacity property?
EDIT: This worked for me (I'm using QtQuick 1.0 because my Qt Creator installation is a bit outdated):
import QtQuick 1.0
Rectangle {
Image {
id: rect
source: "quit.png"
smooth: true
opacity: 1
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; opacity: 0}
PropertyChanges { target: rect2; scale: 0.8; opacity: 1}
}
transitions: Transition {
NumberAnimation { properties: "scale, opacity"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
Image {
id: rect2
source: "quit2.png"
smooth: true
opacity: 0
anchors.fill: rect
}
}
To the question in your comment: you can place the image exactly on top of the other by copying the anchors thru anchors.fill: rect
Here is also a simple scroll transition between images:
import QtQuick 2.6
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: imageRect
anchors.centerIn: parent
width: 240
height: 320
clip: true
property int currentIndex: 0
property var imageSources: [ "imageLeft.jpg", "imageCenter.jpg" ]
Repeater {
model: imageRect.imageSources
Image {
id: image
width: parent.width
height: parent.height
x: index * parent.width - imageRect.currentIndex * parent.width
fillMode: Image.PreserveAspectFit
source: imageRect.imageSources[index]
Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
}
}
}
Button {
id: leftButton
anchors.bottom: parent.bottom
text: "left"
onClicked: if(imageRect.currentIndex > 0) imageRect.currentIndex--
}
Button {
id: rightButton
anchors.bottom: parent.bottom
anchors.left: leftButton.right
text: "right"
onClicked: if(imageRect.currentIndex < imageRect.imageSources.length - 1) imageRect.currentIndex++
}
Button {
id: addButton
anchors.bottom: parent.bottom
anchors.left: rightButton.right
text: "+"
onClicked: imageRect.imageSources = [ "imageLeft.jpg", "imageCenter.jpg" , "imageRight.jpg" ]
}
}

Resources