I faced a conflict in using DropShadow and Ripple - qt

I wrote a Ripple item in a Rectangle Item and enabled clip property of the Rectangle to prevent the Ripple drawing get out of that Rectangle.
without DropShadow:
Everything works fine until I add a DropShadow to that Rectangle. Although it is outside the Rectangle item, but it neutralizes the clip effect in left and right side of the Rectangle.
with DropShadow:
Here is my code:
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12
import QtQuick.Controls.Material.impl 2.12
Item{
width: 400
height: 100
DropShadow {
anchors.fill: itemRect
horizontalOffset: 0
verticalOffset: 0
radius: 12.0
samples: 17
color: "#50000000"
source: itemRect
}
Rectangle{
id:itemRect
anchors.fill: parent;
anchors.margins: 8;
border.width: 1
radius: 5;
clip: true;
MouseArea{
id: button
anchors.fill: parent
onPressed: {
ripple.x=mouseX-(ripple.width/2);
ripple.y=mouseY-(ripple.height/2);
}
Ripple {
id: ripple
clipRadius: 2
x:40
width: itemRect.width*2
height: itemRect.height*2
pressed: button.pressed
active: false
color: "#10000000"
// layer.enabled: true
// layer.effect: OpacityMask {
// maskSource: Rectangle
// {
// width: ripple.height
// height: ripple.height
// radius: ripple.height
// }
// }
}
}
}
}
I tested OpacityMask for layer.effect of Ripple Item. But it didn't have any effects.

Finaly i wrote my own Ripple.
It can be used anywhere without any issues.
https://github.com/mmjvox/Another-Ripple
here is my code:
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12
import AnotherRipple 1.0
Item{
width: 400
height: 100
DropShadow {
anchors.fill: itemRect
horizontalOffset: 0
verticalOffset: 0
radius: 12.0
samples: 17
color: "#50000000"
source: itemRect
}
Rectangle{
id:itemRect
anchors.fill: parent;
anchors.margins: 8;
border.width: 1
radius: 5;
clip: true;
SimpleRipple{
id: ripple
anchors.fill: parent;
color: "#50ffa070"
}
MouseArea{
id: button
anchors.fill: parent
onClicked: {
// In this example MouseArea accepts pressed event to provide clicked(released) event.
// Ripple can't sense pressed event, so I called pressed method of Ripple.
ripple.pressed(mouse.x,mouse.y);
// Some Other Operations
}
}
}
}

Related

Margins and anchors not working good in Qt, QML

I'm new at QML and I have a very confusing situation.
So, this is my main.qml file:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
Window {
id:rootWin
visible: true
width: 350
height: 330
ConnectBox
{
id:boxConnect
MouseArea
{
id: connectMouse
hoverEnabled: true
anchors.fill: boxConnect
}
}
Rectangle {
id: randomRec
width: parent.width/2
height: parent.height/6
// x: 50
anchors.top: boxConnect.bottom
// anchors.horizontalCenter: parent
anchors.topMargin: 10
border.color: "dimgray"
border.width: 5
radius: 14
}
}
ConnectBox.qml:
import QtQuick 2.0
Rectangle {
id: connectRec
width: parent.width/2
height: parent.height/6
anchors.centerIn: parent
border.color: "dimgray"
border.width: 5
radius: 14
}
I want it to be randomRec below boxConnect, so it does but it is all left and it only moves when I put for example x: 50 but its not convenient for every size of the window.
First off: I'd advise to put the anchors that are related to each other all on the same file.
But to get the randomRec to center below the connectBox you should use the following anchors:
Rectangle {
id: rect1
width: 100
height: 200
color: "red"
anchors.centerIn: parent
}
Rectangle {
id: rect2
width: 75
height: 50
color: "yellow"
anchors.top: rect1.bottom
anchors.horizontalCenter: rect1.horizontalCenter
}
So I guess you where almost there, with the horizontalCenter: parent line, which should have .horizontalCenter as well. However, I anchored it on rect1 since that is what you want (let's say you might want to move the boxConnect in the future... you would have to find all of the references)

Apply QML DropShadow invalid, error hint and hint for "QML DropShadow: Cannot anchor to an item that isn't a parent or sibling."

Codes show as below:
import QtQuick 2.12
import QtGraphicalEffects 1.12
import QtQuick.Controls 2.12
Item {
width: 300
height: 300
TabBar {
id: bar
width: parent.width
contentHeight: 38
background: Rectangle {
color: "#477aa0"
}
TabButton {
id: tabBtn1
width: 129
height: 36
text: qsTr("Plate Layout")
anchors.top: parent.top
background: Rectangle {
color: "#ffffff"
}
}
//is tabBtn1's sibling!
DropShadow {
anchors.fill: tabBtn1
horizontalOffset: 3
verticalOffset: 4
radius: 5
samples: 11
color: "#000"
opacity: 0.75
source: tabBtn1
}
}
}
If TabBar change to Rectangle and TabButton change to Button, it works.As far as I know,qml included in brackets by Menu. I guess it is bug of Qt lib, maybe I am wrong.
This is because a DropShadow is not a TabButton, which causes this function to return false and it is not parented to the effective contentItem like the TabButton is. Note that the contentItem is a ListView, so making the DropShadow a child of it and trying to make it then fill the TabButton probably wouldn't work anyway.
An easier solution is to use layers:
TabButton {
id: tabBtn1
width: 129
height: 36
text: qsTr("Plate Layout")
anchors.top: parent.top
background: Rectangle {
color: "#ffffff"
}
layer.enabled: true
layer.effect: DropShadow {
anchors.fill: tabBtn1
horizontalOffset: 3
verticalOffset: 4
radius: 5
samples: 11
color: "#000"
opacity: 0.75
}
}

How to add animation to a component while destroying in QML

I am adding Animation to my project and most of the UI is dynamic. Currently, i am not able to add animation to the Component while destroying. Following is the test application code which describes the same:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property bool removeClicked : true
Row{
anchors.bottom: parent.bottom
spacing:20
Button{
text:"Add"
onClicked: {
removeClicked = false
comp.createObject(myrow)
}
}
Button{
id:remBtn
text:"Remove"
onClicked: {
removeClicked = true
myrow.children[0].destroy() //Destroy the object
}
}
}
Row{
id:myrow
height:40
spacing:20
}
Component{
id:comp
Rectangle{
width:20
height:30
color: "red"
NumberAnimation on opacity{
id: destroyAnimation
from :removeClicked ? 1:0
to: removeClicked ? 0:1
duration: 1000
}
}
}
}
Any help will be Appreciated!!!
Shou should perform the animation before calling destroy on your dynamically created items. You could use a SequentialAnimation, combined with a ScriptAction to do so.
Here's a small example (the dynamic balls get destroyed when one clicks on them).
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
Button{
text:"Add"
anchors.centerIn: parent
onClicked: {
comp.createObject(parent)
}
}
Component{
id:comp
Rectangle{
id: ball
height:30
width:height
radius: height/2
x: Math.random()*parent.width-width
y: Math.random()*parent.height-height
color: Qt.hsla(Math.random(), 0.5, 0.5, 1)
opacity: 0
Component.onCompleted: opacity = 1
Behavior on opacity{ NumberAnimation {}}
SequentialAnimation
{
id: destroyAnim
ScriptAction{script: ball.opacity = 0}
NumberAnimation{target: ball; property:"scale"; to: 5}
ScriptAction{script: ball.destroy()}
}
MouseArea
{
anchors.fill: parent
onClicked:destroyAnim.start()
}
}
}
}

QML pieMenu on draggable object

I've got a draggable object that is created by a Javascript, which is working fine. But when I create a PieMenu inside it, the object isn't created/visible in the Javascript context:
import QtQuick 2.8
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
import QtQml.Models 2.2
Rectangle {
id: rev
width: 100
height: 80
color: "transparent"
antialiasing: false
Drag.active: dragArea.drag.active
MouseArea {
id: dragArea
width: parent.width
height: parent.height + 10 // easier to get
anchors.centerIn: parent
drag.target: parent
drag.axis: Drag.XAndYAxis
onClicked: pieMenu.popup(mouseX, mouseY), console.log("clicked")
}
PieMenu {
id: pieMenu
MenuItem {
text: "Add vertical bar"
onTriggered: print("Action 2")
}
}
Gauge {
id: revgauge
anchors.fill: parent
anchors.margins: 10
orientation : Qt.Horizontal
minorTickmarkCount: 4
tickmarkStepSize : 5000
minimumValue: 0
maximumValue: 10000
Behavior on value {
NumberAnimation {
duration: 5
}
}
Text {
font.pixelSize: (parent.height / 3)
anchors.top : parent.top
font.bold: true
font.family: "Eurostile"
color: "white"
anchors.horizontalCenter: parent.horizontalCenter
}
style: GaugeStyle {
valueBar: Rectangle {
implicitWidth: rev.height /3
color: Qt.rgba(revgauge.value / revgauge.maximumValue, 0, 1 - revgauge.value / revgauge.maximumValue, 1)
}
}
}
}
Can Mousearea handle dragging and a PieMenu at once? If not how can it be solved?
Consider QML PieMenu boundingItem. It addresses an exact issue with MouseArea you presented.

Why does not onReleased fire up after a drag

I have a mouse area that has something like this
onPressed: {
cursorShape = Qt.ClosedHandCursor
console.log("closed")
}
onReleased: {
cursorShape = Qt.OpenHandCursor
console.log("open")
}
cursorShape: Qt.OpenHandCursor
If I click and release without any mouse movement, the cursor icon changes as expected. If I move the mouse while clicked though, the cursor icon remain a closed hand.
Why is that?
I've just checked the behaviour is right with the following code in QML .
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
id: mainwindow
width: 640
height: 480
visible: true
Flickable {
width: 200; height: 200
contentWidth: image.width
contentHeight: image.height
clip: true
Image {
id: image;
source: "images/icon.png"
MouseArea {
anchors.fill: parent
preventStealing: true
onPressed: {
cursorShape = Qt.ClosedHandCursor
console.log("closed")
}
onReleased: {
cursorShape = Qt.OpenHandCursor
console.log("open")
}
cursorShape: Qt.OpenHandCursor
}
}
}
}
Setting preventStealing as true gets the MouseArea working fine and the cursorShape changes ok. But the drawback (a BIG drawback) is the flick gesture is stolen by the MouseArea so the flick movement is not generated.
So, I recommend handling onMovementEnded to set the cursorShape = Qt.OpenHandCursor when the user interaction ends.
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
id: mainwindow
width: 640
height: 480
visible: true
Flickable {
width: 200; height: 200
contentWidth: image.width
contentHeight: image.height
clip: true
onMovementEnded: {
mousearea.cursorShape = Qt.OpenHandCursor
console.log("onMovementEnded")
}
Image {
id: image;
source: "images/icon.png"
MouseArea {
id: mousearea
anchors.fill: parent
onPressed: {
cursorShape = Qt.ClosedHandCursor
console.log("closed")
}
onReleased: {
cursorShape = Qt.OpenHandCursor
console.log("open")
}
cursorShape: Qt.OpenHandCursor
}
}
}
}

Resources