How to create a prespective image in qml - qt

I am trying to create perceptive image from a normal image
I need something like this
from something like this
I tried different ways like rotate and use a mask like this
Image {
id: bug
source: "./Graphics/sample.png"
width: 200
height: 200
anchors.centerIn: parent
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 46 }
visible: true
layer.enabled: true
layer.effect: OpacityMask {
maskSource:
Image {
id: mask
source: "./mask.png"
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
visible: false
}
}
}
Is there any proper way to actually create an effect like this.

I am not sure, if I got it right, but is it something like this, you want to achive?
Item {
width: 1000
height: 500
anchors.centerIn: parent
RectangularGlow {
id: effect
anchors.fill: img
glowRadius: 25
spread: 0.2
color: "black"
cornerRadius: 50
}
Image {
id: img
anchors.centerIn: parent
width: 1000
height: 500
source: 'source.png'
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: 1000
height: 500
radius: 25
}
}
}
transform: Rotation { axis {x: 0.5; y: 1; z: 0} angle: 45 }
}
Or maybe it is a DropShadow you want to apply, instead of the RectangularGlow
DropShadow {
anchors.fill: img
horizontalOffset: -15
verticalOffset: 8
radius: 20
samples: 40
color: "#80000000"
source: Rectangle {
width: 1000
height: 500
radius: 25
}
}

Related

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

QT QML Circle and a text listview

I wanted to create an UI similar to below images. I understand Qt Pathview helps me to move the items in an circular fashion. But I couldn't get how to create the background similar to the images with equal space between the text. I tried with rectangle (radius:360) to draw circle, but the pathview items doesn't move along the center of the rectangle-circle.
Maybe this simple example could help you with PathView:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 400
height: 400
Item {
id: container
width: 300
height: 300
anchors.centerIn: parent
Rectangle {
anchors.fill: parent
radius: width /2
color: "orange"
Rectangle {
x: 50
y: 50
width: 200
height: 200
radius: 100
color: "white"
}
}
PathView {
anchors.fill: parent
model: 10
delegate: Rectangle {
width: 50
height: 50
radius: 25
color: "green"
}
path: Path {
startX: 150; startY: 25
PathArc {
x: 150; y: 275
radiusX: 125; radiusY: 125
direction: PathArc.Clockwise
}
PathArc {
x: 150; y: 25
radiusX: 125; radiusY: 125
direction: PathArc.Clockwise
}
}
}
}
}

Position of mouse on image

I have two images:
1. normal image
2. same image with the ability to zoom.
I have 4 draggable shapes (A,B,C,D) on second image (image with the ability to zoom).
I want to display position of mouse on normal image (with draw a shape (canvas3)) when the position of A/B/C/D shapes changed on the zoomed image.
I used the following code but it does not show correct position. In fact, I want user can see position of mouse.
property int xwheel: 0
property int ywheel: 0
property alias source :image.source
id:mywin
property int highestZ: 0
property real defaultSize: mywin.width
property real surfaceViewportRatio: 1.5
ScrollView {
anchors.fill: parent
flickableItem.interactive: true
frameVisible: true
highlightOnFocus: true
style: ScrollViewStyle {
transientScrollBars: true
.........
}
Flickable {
id: flick
anchors.fill: parent
contentWidth: parent.width
contentHeight: parent.height
Rectangle {
id: photoFrame
width: parent.width
height: parent.height
scale:defaultSize / parent.width
Behavior on scale { NumberAnimation { duration: 200 } }
Behavior on x { NumberAnimation { duration: 200 } }
Behavior on y { NumberAnimation { duration: 200 } }
smooth: true
antialiasing: true
Image {
id:image
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
}
PinchArea {
anchors.fill: parent
pinch.target: photoFrame
pinch.minimumRotation: -360
pinch.maximumRotation: 360
pinch.minimumScale: 0.1
pinch.maximumScale: 10
pinch.dragAxis: Pinch.XAndYAxis
property real zRestore: 0
onSmartZoom: {
.....
}
MouseArea {
id: dragArea
hoverEnabled: true
anchors.fill: parent
drag.target: photoFrame
scrollGestureEnabled: false
onPressed: {
photoFrame.z = ++mywin.highestZ;
}
onWheel: {
...
}
}
Point {
id: pointA
onDragged: {
xwheel=pointA.x;
ywheel=pointA.y;
canvas3.requestPaint()
}
}
//Point B
//Point D
//Pint C
}
}
}
Image {
id:mainimage
width: parent.width/4
height: parent.height/4
smooth: true
source: image.source
Canvas {
id: canvas3
width: parent.width
height: parent.height
onPaint: {
var context = getContext("2d");
// Make canvas all white
......
context.beginPath();
//Style
.......
context.moveTo(xwheel/4, ywheel/4);
context.arc(xwheel/4, ywheel/4, 5, 0, 2*Math.PI, true)
context.fill();
context.stroke();
}
}
}

How to add animation onPressed and onReleased in QML Slider?

http://doc.qt.io/qt-5/qml-qtquick-controls-styles-sliderstyle.html
Slider {
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
How to access the onReleased and onPressed of the slider in order to start and stop some animation?
Here is what I tried:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
returnAnimation.stop()
}
else
{
console.log("released")
returnAnimation.start()
}
}
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
}
}
Error:
ReferenceError: thumb is not defined
Here is a fully working example. You will have to create your own images referenced here since I can't attach them.
I have found scoping is tricky in QML with component objects. The ":style:handle" component in Slider can "see out" to the higher levels but the higher levels cannot "see in" to the ":style:handle" component.
General Strategy
Create a property in the Top Level Slider scope
Use the property inside the ":style:handle" component since it can "see out"
Use the higher level onPressedChanged handler and the pressed property to adjust the high level property which will be "seen" by the low level component.
Slider {
id: portVoltageSlider
width: 100; height: 27
maximumValue: 150; minimumValue: -150
value: 0.00
stepSize: 10
anchors { centerIn: parent }
// style:handle component will be able to see/access this property
// opacity value of style: SliderStyle:handle.sliderHover
property real hoverOpacity: 0
// adjust property on slider pressed
onPressedChanged: {
// show slider Hover when pressed, hide otherwise
if( pressed ) {
console.log("slider pressed. show hover.")
hoverShowAnimation.start()
}
else {
console.log("slider released. hide hover.")
hoverHideAnimation.start()
}
}
// gratuitous animation using opacity
PropertyAnimation {
id: hoverShowAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 1; duration: 500
}
PropertyAnimation {
id: hoverHideAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 0; duration: 500
}
style: SliderStyle {
id: sliderStyle
property bool hoverVisible: false
groove: Rectangle {
// x: slider1.leftPadding
y: portVoltageSlider.topPadding + portVoltageSlider.availableHeight / 2 - height / 2
implicitWidth: 200; implicitHeight: 4
width: portVoltageSlider.availableWidth; height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
width: portVoltageSlider.visualPosition * parent.width; height: parent.height
color: "yellow"
radius: 2
}
}
handle: Image {
id: sliderHandle
width: 22; height: 24
source: "sliderThumb.svg"
anchors { centerIn: parent }
Image {
id: sliderHover
width: 22; height: 24
source: "sliderValue.svg"
anchors { bottom: sliderHandle.top }
opacity: portVoltageSlider.hoverOpacity
Label {
id: check
anchors {centerIn: parent; verticalCenterOffset: -4 }
text: portVoltageSlider.value
font.pointSize: 6
font.bold: true
}
}
}
}
}
That what I meant in the comment above:
Slider {
...
onPressedChanged: {
if(pressed)
console.log("pressed")
else
console.log("released")
}
}
Would this work?
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
//Added these signals:
signal startAnim
signal stopAnim
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
//Moved animation within the confines of the object that it actually pertains to
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
//Signal connections done here:
Component.onCompleted: {
head.startAnim.connect(returnAnimation.start)
head.stopAnim.connect(returnAnimation.stop)
}
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
startAnim()
}
else
{
console.log("released")
stopAnim()
}
}
}
}

Animation of y position for a Column centerd in parent

I have a Column with three elements and one element can change its visibility if the user hits the spacebar. To make the visibility change look smoothly I can add a move transition:
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
Column {
spacing: 2
Rectangle { color: "red"; width: 50; height: 50 }
Rectangle { id: greenRect; color: "green"; width: 20; height: 50 }
Rectangle { color: "blue"; width: 50; height: 20 }
move: Transition {
NumberAnimation { properties: "x,y"; duration: 1000 }
}
focus: true
Keys.onSpacePressed: greenRect.visible = !greenRect.visible
}
}
This works. But if I center the Column in its parent the visibility change also results in a new height for the Columnand therefore also to a new y position.
Now I don't want the Column to 'jump' to its new position but also to move smoothly. So I added this to the Column:
anchors.centerIn: parent
Behavior on y {
NumberAnimation { duration: 1000 }
}
But the y position change is still not animated. How to achieve this?
I added another Item element which holds the Column. This allows you to set a Behavior on the item's height property and is what you're looking for:
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
width: 640
height: 480
visible: true
Item {
id: container
width: col.width
height: col.height
anchors.centerIn: parent
property int animationDuration: 200
Behavior on height {
PropertyAnimation {
duration: container.animationDuration
}
}
Column {
id: col
spacing: 2
focus: true
Rectangle { color: "red"; width: 50; height: 50 }
Rectangle { id: greenRect; color: "green"; width: 20; height: 50 }
Rectangle { color: "blue"; width: 50; height: 20 }
move: Transition {
NumberAnimation { properties: "x,y"; duration: container.animationDuration }
}
Keys.onSpacePressed: greenRect.visible = !greenRect.visible
}
}
}
Hope this helps!
Property changes induced by anchors don't seem to trigger Behaviours.
As a workaround, manually center the Column:
import QtQuick 2.2
Rectangle {
width: 640
height: 480
Column {
spacing: 2
anchors.horizontalCenter: parent.horizontalCenter
y: (parent.height - height) / 2
Behavior on y {
NumberAnimation { duration: 1000 }
}
Rectangle { color: "red"; width: 50; height: 50 }
Rectangle { id: greenRect; color: "green"; width: 20; height: 50 }
Rectangle { color: "blue"; width: 50; height: 20 }
move: Transition {
NumberAnimation { properties: "x,y"; duration: 1000 }
}
focus: true
Keys.onSpacePressed: greenRect.visible = !greenRect.visible
}
}

Resources