Activating an animation in an imported (reusable) object
-
I would like to make a reusable component with an animation, but I would like to activate that animation from the main.qml file. How do I do this?
main.qml:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import "objects" Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.animationRect.running = true } } } }
objects/ExpandingRect.qml:
import QtQuick 2.15 Rectangle { color: "red" height: 50 width: 50 PropertyAnimation{ id: animationRect target: parent property: "width" to: if (parent.width == 50) return 200; else return 50 duration: 500 easing.type: Easing.InOutQuint } }
I'm sure it's very simple. Can anyone tell me how to get this to work please?
Thank you.
-
hi, in the following code you don't have access to animationRect by id like you are trying
@Mlibu said in Activating an animation in an imported (reusable) object:
onClicked: { expandingRect.animationRect.running = true
you can create an alias in ExpandingRect.qml to make the PropertyAnimation object accessible, or have a function that starts the timer
///ExpandingRect.qml Rectangle { property alias animAlias : anim // custom function function startAnimation(){ anim.start() //... //... } color: "red" height: 50 width: 50 SequentialAnimation on width { id: anim running: false loops: Animation.Infinite PropertyAnimation { to: 50 } PropertyAnimation { to: 200 } } }
Window { width: 640 height: 480 visible: true Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.animAlias.running = true // or expandingRect.animAlias.start() // custom function // expandingRect.startAnimation() } } } }
-
Ok so I tried both these options, but obviously I am doing something wrong because it's not working. Do I need to use SequentialAnimation instead of PropertyAnimation? It seems the two should be fairly similar. Though I just want to animate once each press but toggle between a width of 50 and 200.
main.qml:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import "objects" Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.toggle() } } } Component.onCompleted: { console.log("OUTPUT") } }
objects/ExtendingRect.qml:
import QtQuick 2.15 Rectangle { id: menuRect color: "red" height: 50 width: 50 property alias animationAlias : animationRect function toggle() { animationAlias.running = true } PropertyAnimation{ id: animationRect target: parent property: "width" to: if (parent.width == 50) return 200; else return 50 duration: 500 easing.type: Easing.InOutQuint } Component.onCompleted: { } }
I tried it with SequentialAnimation as well but it doesn't work either:
objects/ExpandingRect.qml:import QtQuick 2.15 Rectangle { id: menuRect color: "red" height: 50 width: 50 property alias animationAlias : animationRect function toggle() { animationAlias.start() } // PropertyAnimation{ // id: animationRect // target: parent // property: "width" // to: if (parent.width == 50) return 200; else return 50 // duration: 500 // easing.type: Easing.InOutQuint // } SequentialAnimation on width { id: animationRect running: false loops: Animation.Infinite PropertyAnimation { to: if (parent.width === 50) return 200; else return 50 } //PropertyAnimation { to: 200 } } Component.onCompleted: { } }
-
@Mlibu the example i gave u is working, i tested it before i past the code here.
You do not have to use PropertyAnimation, you can use anything you want
here is an example with the Behavior QML typeRectangle { id: rec color: "red" height: 50 width: 50 function startAnimation(){ if (rec.width <= 50){ rec.width = 200 }else{ rec.width = 50 } } Behavior on width {NumberAnimation{duration: 500}} }
Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.startAnimation() } } } }
please note that i used the alias to access an object from the outside (when it is reused somewhere else )
what you did :property alias animationAlias : animationRect function toggle() { animationAlias.running = true } PropertyAnimation{ id: animationRect
is not needed to have an alias, your function can access the PropertyAnimation object directly by id like this
function toggle() { animationRect.running = true } PropertyAnimation{ id: animationRect
your problem comes from this line
to: if (parent.width == 50) return 200; else return 50
you can verify that just by replacing your javascript if statement by a hardcoded value..
You can simply use Behavior as i showed
-
So I cannot use your example directly because I want the animation to extend width to 200 once if the width is 50, or reduce the width to 50 once if the width is 200. It's a toggle to show a menu drawer.
I made my code exactly as you specified. I used the function method and I also took out the javascript for the to: width and hard coded it to 200. It should extend the square to 200 on the first button press but it is not working. What am I doing wrong here? My impression is that I am following everything you have told me. I think I suspect the use of 'parent' in the PropertyAnimation as the issue. It works if I put it all into main.qml and replace 'parent' with a hard coded ID. But I am not hard coding the ID in the case of a reusable component.
main.qml:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import "objects" Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.toggle() } } } Component.onCompleted: { console.log("OUTPUT") } }
objects/ExpandingRect.qml:
import QtQuick 2.15 Rectangle { color: "red" height: 50 width: 50 function toggle() { animationRect.running = true } PropertyAnimation{ id: animationRect target: parent property: "width" //to: if (parent.width == 50) return 200; else return 50 to: 200 duration: 500 easing.type: Easing.InOutQuint } Component.onCompleted: { } }
-
@Mlibu said in Activating an animation in an imported (reusable) object:
So I cannot use your example directly because I want the animation to extend width to 200 once if the width is 50, or reduce the width to 50 once if the width is 200. It's a toggle to show a menu drawer.
why not just use Behavior type like in my last example ? it seems like it does exactly what you need
there is also a ready to use Drawer QML type https://doc.qt.io/qt-6/qml-qtquick-controls2-drawer.html
-
The built in drawer QML type cannot reduce to a minimum width to still display icons and have them be selectable as far as I could see. It seemed to be more like a mobile device app drawer than a desktop application drawer. That's why I only reduce width to 50. I will look at the Behavior type. I guess you are saying that PropertyAnimation is not suited to this purpose.
Question: To use behavior, you have the id 'rec' defined on the Rectangle, but I want to define the id in main.qml on the definition of ExpandingRectangle. How do I do the startAnimation() with Behavior if there is no id in the object?
-
I got it to work by giving the rectangle a static id but wrapping it in an Item. I put the toggle function in the item to expose it and set the width and the height of the item to the rectangle width and height so the column would work properly. This way the item gets the id set from main.qml and everything references properly.
main.qml:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import "objects" Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Column { ExpandingRect { id: expandingRect } Button { text: "change rect" onClicked: { expandingRect.toggle() } } } Component.onCompleted: { console.log("OUTPUT") } }
objects/ExpandingRect.qml:
import QtQuick 2.15 Item { function toggle() { animationRect.running = true } width: leftMenuRect.width height: leftMenuRect.height Rectangle { id: leftMenuRect color: "red" height: 50 width: 50 PropertyAnimation{ id: animationRect target: leftMenuRect property: "width" to: if (leftMenuRect.width == 50) return 200; else return 50 //to: 200 duration: 500 easing.type: Easing.InOutQuint } Component.onCompleted: { } } }