How do I make a gradient opacity in an image? - qt

How do I make an image fade in qml? How do I achieve this effect? here I attach the image of how I want it to look

A possible solution is to use OpacityMask with a LinearGradient as source
import QtQuick 2.9
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 600
height: 600
title: qsTr("Hello World")
Image {
id: input
source: "input.jpg"
anchors.fill: parent
OpacityMask {
source: mask
maskSource: input
}
LinearGradient {
id: mask
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.2; color: "transparent"}
GradientStop { position: 0.5; color: "white" }
}
}
}
}
Input:
Output:

While the accepted solution achieves the desired effect, it's not actually creating an opacity gradient in the original image (which is what I needed). It's just overlaying the LinearGradient on top of the image; the OpacityMask isn't doing anything and can be removed from that example. The white color at the bottom of the image is from the LinearGradient, not from the background.
Here's an example of how to create an opacity gradient in the original image. Note that the visibility of the "source image" (a Rectangle, in this case) and the LinearGradient are both false.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 400
height: 400
title: qsTr("Hello World")
// The background, to ensure it's working
Rectangle {
color: "red"
anchors.fill: parent
}
// The "source image"
Rectangle {
id: blueBox
color: "blue"
anchors.fill: parent
opacity: 0.5
visible: false
}
LinearGradient {
id: mask
anchors.fill: blueBox
gradient: Gradient {
GradientStop {
position: 0.2
color: "transparent"
}
GradientStop {
position: 0.5
color: "white"
}
}
visible: false
}
OpacityMask {
anchors.fill: parent
source: blueBox
maskSource: mask
}
}

With few lines code:
LinearGradient {
source: Image { source: 'qrc:/Login Images/ir.svg' }
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(0, 300)
gradient: Gradient {
GradientStop { position: 0.0; color: "white" }
GradientStop { position: 1.0; color: "teal" }
}
}

Related

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 { ... }
}

Qml rounded corner of one side with border

Is there a way to have a Rectangle with one side rounded edges and also a border in Qt without using the Canvas.
Something like below.
I did try below code and I am able to create the rounded corner on one side.
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
width: 200
height: 200
visible: true
Item {
width: 100
height: 50
opacity: 0.5
layer.enabled: true
anchors.centerIn: parent
Rectangle {
color: "blue"
radius: 10
anchors.fill: parent
}
Rectangle {
color: "blue"
anchors.fill: parent
anchors.leftMargin: 10
}
}
}
With above code I am able to get the one side rounded corners but when I add border then I see overlapping borders.
Is there a clean way of doing this in Qml?
I can think of two ways to do that.
Not the "cleanest" way, but probably the simplest performance-wise. You can keep using the code you have above, but just draw another non-bordered rectangle that covers up the extra border line that you are seeing.
property int borderWidth: 4
Item {
width: 100
height: 50
opacity: 0.5
layer.enabled: true
anchors.centerIn: parent
Rectangle {
id: roundCorners
color: "blue"
radius: 10
border.width: borderWidth
anchors.fill: parent
}
Rectangle {
id: squareCorners
color: "blue"
border.width: borderWidth
anchors.fill: parent
anchors.leftMargin: 10
}
Rectangle {
anchors.left: squareCorners.left
anchors.verticalCenter: squareCorners.verticalCenter
width: borderWidth
height: squareCorners.height - borderWidth * 2
color: "blue"
}
}
You can use QML's Shape object and use a ShapePath to define it. The docs can be found here.
Shape {
ShapePath {
strokeWidth: 4
strokeColor: "black"
fillColor: "blue"
PathLine { ... }
PathLine { ... }
PathLine { ... }
PathArc { ... }
}
}

QML layer element "reveals" element above it when they overlap

Is it possible in QML, maybe using shader effects with layers, to create an item that makes another item (with a higher z index) visible only when the two layers overlap? I've been messing aroud with OpacityMask and ThresholdMask but have been unable to figure it out. The effect I'm looking for in the context of the example below would be if the the black circle was only visible when the two red squares are under it:
current:
desired:
Some key points are that the bottom layer (red squares) must be moveable (OpacityMask doesn't seem to let you drag the maskSource) and the bottom layer needs to also be able to contain other elements within it that the black circle responds to. Any guidance towards the right things to learn in order to achieve this would be appreciated. Here is the QML for the red squares and black circle thing. The red squares are draggable as one element:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12
Window {
id: main_window
visible: true
width: 1500
height: 1000
title: qsTr("Hello World")
Item {
width: main_window.width
height: main_window.height
LinearGradient {
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(main_window.width, 0)
gradient: Gradient {
GradientStop { position: 0.0; color: "#003cff" }
GradientStop { position: 1.0; color: "#9afff9" }
}
}
}
Rectangle {
id: sfg
width: 175
height: 75
color: 'transparent'
RowLayout {
width: parent.width
height: parent.height
spacing: 25
Rectangle {
Layout.preferredWidth: 75
Layout.fillWidth: false
Layout.fillHeight: true
color: 'red'
}
Rectangle {
Layout.preferredWidth: 75
Layout.fillWidth: false
Layout.fillHeight: true
color: 'red'
}
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
drag {
target: sfg
}
}
}
Rectangle {
id: mask
color: 'black'
x: 400
y: 200
width: 100
height: 100
visible: true
opacity: 1
radius: 50
}
}
Like this?
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12
Window {
id: main_window
visible: true
width: 1500
height: 1000
title: qsTr("Hello World")
Item {
width: main_window.width
height: main_window.height
LinearGradient {
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(main_window.width, 0)
gradient: Gradient {
GradientStop { position: 0.0; color: "#003cff" }
GradientStop { position: 1.0; color: "#9afff9" }
}
}
}
Rectangle {
id: sgfBox
anchors.fill: parent
color: "transparent"
Rectangle {
id: sfg
width: 175
height: 75
color: 'transparent'
RowLayout {
width: parent.width
height: parent.height
spacing: 25
Rectangle {
Layout.preferredWidth: 75
Layout.fillWidth: false
Layout.fillHeight: true
color: 'red'
}
Rectangle {
Layout.preferredWidth: 75
Layout.fillWidth: false
Layout.fillHeight: true
color: 'red'
}
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
drag {
target: sfg
}
}
}
}
Rectangle {
id: mask
anchors.fill: parent
color: "transparent"
Rectangle {
color: 'black'
x: 400
y: 200
width: 100
height: 100
opacity: 1
radius: 50
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource: sgfBox
}
}
}

QML PieSlice Gradient colour

I'm using a PieSeries in QML as a way to create a makeshift mask.
I have a circular animated gif and on top of it, I've added a PieSeries.
The PieSeries has 3 PieSlices. 2 of them are "black" essentially blocking out there corresponding portions of the gif. The remaining PieSlice is transparent.
This works fine, but I would like the 2 black PieSlices to have a gradient to them so that their edge is not so obvious (gradient transparency).
I've tried using a LinearGradient with an OpacityMask as described here, but this did not have any effect when used on a PieSlice.
Any suggestions would be appreciated :)
Here's my code:
import QtQuick 2.0
import QtCharts 2.2
import QtGraphicalEffects 1.0
Item {
anchors.fill: parent //Fill the gif area
ChartView {
id: chart
anchors.centerIn: parent
height: parent.height+200
width: parent.width
legend.visible: false
antialiasing: false
backgroundColor: "transparent"
PieSeries {
id: pieOuter
size: 1.5
holeSize: 0.2
PieSlice { id: black1; value: 1; color: "black"; borderColor: "transparent" }
PieSlice { id: valSlice; value: d.val; color: "transparent"; borderColor: "transparent" }
PieSlice { id: black2; value: 1 - d.val; color: "black"; borderColor: "transparent" }
}
}
OpacityMask{
source: mask
maskSource: black1
}
LinearGradient {
id: mask
anchors.fill: black1
gradient: Gradient {
GradientStop { position: 0.2; color: "transparent"}
GradientStop { position: 0.5; color: "white" }
}
}
}
Note: d.val here holds a value between 0 and 1
Edit
Some images to help visualise what I'm trying to achieve:
The GIF that I'm starting off with (source - original file was too large to attach):
Snapshot of original Gif
This is how it is currently animated to look:
Low d.val
Higher d.val
Max d.val
This is what I want it to actually look like (depicted here for d.val):
Higher d.val with gradient

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.

Resources