I would like to have an application, where always when new image is loaded, it is appeared by scaling from 0 size to default size. This behavior is often not working. In this image I am also using animation for bouncing when mouse enters to image. Is it possible, that this two animations are not loving themselves and that is, why scaling up is often not working?
I am using Linux Mint 13, Qt 5.3
Here is my Image element:
Image {
id: pic1
width: appWindow.height*0.4
height: appWindow.height*0.4
smooth: { enabled = true
pic1MouseArea.containsMouse
}
states: [ "mouseIn", "mouseOut" ]
state: "mouseOut"
transitions: [
Transition {
from: "*"
to: "mouseIn"
NumberAnimation {
target: pic1
properties: "scale"
from: 0.95
to: 1
duration: 400
easing.type: Easing.OutBounce
}
}
]
scale: {
status === Image.Ready ? 1 : 0
}
Behavior on scale {
NumberAnimation{
from: 0
to: 1
duration: 1000
easing.type: Easing.OutBounce
}
}
MouseArea{
id: pic1MouseArea
hoverEnabled: true
anchors.fill: parent
onContainsMouseChanged: {
pic1.state = containsMouse ? "mouseIn" : "mouseOut"
}
onClicked: {
MyScript.getRandomFile()
}
}
}
First of all, read this doc. The states property must be defined as list<State>, not as an array of strings. Also, the State element defines some state when a property or set of properties changes from default configuration. In your example states define nothing. Read more about State type.
Finally, here is a small example to help you getting on:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
Window {
width: 600
height: 400
visible: true
Image {
id: img
source: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"
anchors.centerIn: parent
opacity: 1
state: "mouseOut"
states: [
State {
name: "mouseIn"
PropertyChanges { target: img; opacity: 0 }
},
State {
name: "mouseOut"
PropertyChanges { target: img; opacity: 1 }
}
]
transitions: Transition {
PropertyAnimation {
target: img
property: "opacity"
easing.type: Easing.InCirc
duration: 1000
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: img.state = "mouseIn"
onExited: img.state = "mouseOut"
}
}
}
Sure, you can replace transitions with Behavior, if you need exactly this functionality, as shown below:
Behavior on opacity {
PropertyAnimation {
duration: 1000
easing.type: Easing.InCirc
}
}
Related
why doesn't animation in the left work in the first case?
qmlonline.
if you go to the second case and comment out the code with when, then the animation works. the same problem if you disable sequential animation.
this is the first case without animation
this is the second case with animation
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
id: root
property int type: 0
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea {
anchors.horizontalCenter: parent.horizontalCenter
width: 50
height: 50
Rectangle { anchors.fill: parent; color: "blue" }
onClicked: {
root.type = !root.type
// stG.state = root.type ? "right" : "left" // uncomment to the second case
}
}
Rectangle {
id: switcher1
width: 50
height: 50
color: "red"
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: switcher2
width: 50
height: 50
color: "green"
anchors.top: switcher1.bottom
anchors.topMargin: 10
}
StateGroup {
id: stG
states: [
State {
name: "left"
when: type === 0 // comment to the second case
PropertyChanges {
target: switcher1
x: 0
}
PropertyChanges {
target: switcher2
x: 0
}
},
State {
name: "right"
when: type === 1 // comment to the second case
PropertyChanges {
target: switcher1
x: root.width - switcher1.width
}
PropertyChanges {
target: switcher2
x: root.width - switcher2.width
}
}
]
transitions: [
Transition {
to: "left"
SequentialAnimation {
NumberAnimation {
target: switcher2
property: "x"
duration: 500
}
NumberAnimation {
target: switcher1
property: "x"
duration: 500
}
}
},
Transition {
to: "right"
SequentialAnimation {
NumberAnimation {
target: switcher1
property: "x"
duration: 500
}
NumberAnimation {
target: switcher2
property: "x"
duration: 500
}
}
}
]
}
}
that's enough
I can give you a way to fix the problem, but it actually feels like there might be a bug with Qt here.
I tried adding a printout to show me what state Qt thinks it's in:
onStateChanged:
{
console.log("state: " + stG.state);
}
The output I got was this:
// First click
> state: right
// Second click
> state:
> state: left
So, what seems to be happening is that for a split second, the state enters some non-existent state and resets your x-values to 0 without using the transitions. Then the correct state gets applied, but we don't see the transition because everything is already at 0. Maybe someone smarter than me can help figure out why we switch to the bad state first.
Thankfully, there is a simple enough fix. If you make the "right" transition reversible, then it works as expected.
Transition {
to: "right"
reversible: true
...
}
I'm using a QML ListView with section, click on item to remove with animation. Here the code:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
visible: true
width: 400
height: 400
ListView {
id: list
anchors.fill: parent
clip: true
spacing: 0
onContentYChanged: console.log("onContentYChanged: " + contentY)
onContentHeightChanged: console.log("onContentHeightChanged: " + contentHeight)
model: ListModel {
id: myModel
ListElement {name: "Item 1";type: "A"}
ListElement {name: "Item 2";type: "A"}
ListElement {name: "Item 3";type: "B"}
}
delegate: Rectangle {
width: parent.width
height: 50
color: (index % 2 == 1) ? "#5678a2" : "#88a345"
Text {
anchors.verticalCenter: parent.verticalCenter
text: name
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("remove: " + index + ", contentY:" + list.contentY)
myModel.remove(index)
}
}
}
section.property: "type"
section.delegate: Rectangle {
height: 30
Text {
anchors.verticalCenter: parent.verticalCenter
text: section
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutCubic }
}
remove: Transition {
NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 500 }
NumberAnimation { property: "scale"; from: 1.0; to: 0; duration: 500 }
}
}
}
When I clicked on the first item(Item 1), it got deleted, but the Item 2 was flying up to outside the window. The ListView displayed the remaining items in wrong positions. ContentY changed to 80 (which was the y position of Item 2 before) instead of remaining at 0.
qml: onContentHeightChanged: 300
qml: onContentHeightChanged: 240
qml: onContentHeightChanged: 210
qml: remove: 0, contentY:0
qml: onContentYChanged: 80
qml: onContentHeightChanged: 160
It will work correctly if:
Delete other items except the top one.
Disable either the section or animation.
I tried your code with Qt 5.13.1. And currently downloading Qt 5.15. For now it looks like it is a bug with section, because I found a lot of not not closed bug reports on bugtracker. I can suggest 2 ways of solving your problem.
Performing animation while locking removal.
Using model with categories.
1st solution I tested by meself. Here is what you need to change to try it:
Delete ListView's removal animations. Add following code to your delegate
ListView.onRemove: SequentialAnimation {
PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
ParallelAnimation {
NumberAnimation { target: wrapper; property: "opacity"; to: 0; duration: 500 }
NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 500 }
}
PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
}
What is this? ListView has a signal remove() which is called BEFORE removing an item from the view. It is described in documentation It is also noted, that
If a remove transition has been specified, it is applied after this signal is handled, providing that delayRemove is false.
So in delegate you simply block removal from view, do you animation and unblock it. I suppose it won't be as clean and beautiful as you want it to be simply because view doesn't andjust it's size in this case.
2nd solution
I didn't try to implement it, but I can imagine having a model like this:
ListModel {
id: myModel
ListElement { type: "category"; name: "cat1" }
ListElement { name: "delegate1"; type: "delegate"; catrgory: "cat1"}
ListElement { name: "delegate2"; type: "delegate"; catrgory: "cat1"}
ListElement { name: "delegate3"; type: "delegate"; catrgory: "cat1"}
ListElement { type: "category"; name: "cat2" }
ListElement { name: "delegate4"; type: "delegate"; catrgory: "cat2"}
To use this as you want, you will need to castomize your delegate accordingly and removal function accordingly, which will lead to much more complex code in comparison to what it would be if section would work properly.
UPD: Same problem in 5.15
I have the following QML file. I wan't the rectangle myRect to slide in from the right when the root item is clicked (simplified setup). What actually happens is that myRect appears immediately when the root item is clicked.
I checked the running property on the transition and that seems to be fine. It logs true when I click the root item, and then false after 2 seconds.
Does anyone know why the x property doesn't gradually change?
import QtQuick 2.7
Item{
id: root
MouseArea{
anchors.fill: parent
onClicked: {
myRect.state = "visible"
}
}
Rectangle{
id: myRect
width: root.width
height: root.height
state: "hidden"
color: "yellow"
states: [
State {
name: "hidden"
PropertyChanges{
target: myRect
x: myRect.width
}
},
State {
name: "visible"
PropertyChanges{
target: myRect
x: 0
}
}
]
transitions: [
Transition {
NumberAnimation{
duration: 2000
}
onRunningChanged: {
console.log("Running:", running)
}
}
]
}
}
You have to indicate the property, in your case "x"
NumberAnimation{
duration: 2000
properties: "x"
}
There is window, its layout designed by states and transition. we know that when the state change, the transition-animation will start automatically, but when the transition animation doesn't finished, i change the state, it make troubles. just like slow in reacting; how to fix it? thank you...
it something like this :
Flickable {
id: content
anchors.fill: parent
flickableDirection: Flickable.HorizontalFlick
contentWidth: width * 2
contentHeight: height
clip: true
onFlickStarted: {
if(horizontalVelocity > 0) {
regAndFind.state = "Find"
}
else {
regAndFind.state = "Register"
}
} .......
}
states: [
State {
name: "Register"
PropertyChanges {
target: slider
x: 0
}
PropertyChanges {
target: content
contentX: 0
}
},
State {
name: "Find"
PropertyChanges {
target: slider
x: parent.width / 2
}
PropertyChanges {
target: content
contentX: parent.width
}
}
]
transitions: [
Transition {
NumberAnimation {
target: slider
property: "x"
duration: 600
}
NumberAnimation {
target: content
property: "contentX"
duration: 600
}
}
]
Read about the animation element in Qml.
Before you move to other state, you can call the Animation::stop () function to stop the animation in between. Note that it will stop the animation immediately, and the animation will have no further effect on the property values.
I'm trying to get an QML animation to Start every time it's clicked, without using States. It Starts the first time it's clicked, but then won't Start when it's clicked a second time.
Is there a reason why? Here's the code I'm working it.
Image {
id: head;
source: "vlad.png";
height: 80;
width: 90;
MouseArea {
anchors.fill: parent
onClicked: animateHead.start();
ParallelAnimation {
id: animateHead;
NumberAnimation {
property int randomValueX: 0;
function randomize(randomValueX) {
randomValueX = (Math.floor(Math.random()*210));
return randomValueX;
}
target: head;
properties: "x";
to: randomize(randomValueX);
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
NumberAnimation {
property int randomValueY: 0;
function randomize(randomValueY) {
randomValueY = (Math.floor(Math.random()*210));
return randomValueY;
}
target: head;
properties: "y";
to: randomize(randomValueY);
duration: 700;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
}
}
}
The problem is that the values of the to properties of the two NumberAnimation instances are bound only once during initialization of the QML component. They are not recalculated when you call animateHead.start() and animations are only executed if the value of the to property differs from the actual value of the animated property. That's why it works only the first time.
A working solution would be:
import QtQuick 1.0
Image {
id: head;
source: "vlad.png";
height: 80;
width: 90;
MouseArea {
anchors.fill: parent
onClicked: {
xAnimation.to = Math.floor(Math.random()*210)
yAnimation.to = Math.floor(Math.random()*210)
animateHead.start();
}
ParallelAnimation {
id: animateHead;
NumberAnimation {
id: xAnimation
target: head;
properties: "x";
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
NumberAnimation {
id: yAnimation
target: head;
properties: "y";
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
}
}
}
Here the values of the to properties are set explicitly in the onClicked handler of the MouseArea.
Just as a note, because I was trying to solve similar problem, googled this question and decided that there must be another way of dealing with animated property initialization. In Qt 5 you can use the PropertyAction to instantly initialize some properties.
Example from PropertyAction type documentation:
SequentialAnimation {
PropertyAction { target: img; property: "opacity"; value: .5 }
NumberAnimation { target: img; property: "width"; to: 300; duration: 1000 }
PropertyAction { target: img; property: "opacity"; value: 1 }
}
I don't know how would it interact with ParallelAnimation but it works very good with SequentialAnimation.