[solved] Running an Animation before an item is made non-visible?



  • I have a Item which I switch on and off. The visible property is useful for toggling between the on and off states.

    I would also like to add an animation so that the item slides into place when it is switched on, and slides out again when switched off.

    Looking at the documentation for Animation and Behavior, however, it looks as though this is not as easy to achieve as I would like. Something like the following would intuitively have made sense:
    @ Behavior on visible {
    NumberAnimation {
    target: itemId
    property: "y"
    from: visible ? -itemId.height : 0
    to: visible ? 0 : -itemId.height
    }
    }
    @

    And this does work when visible goes to true. The item is visible and you can see the animation bring the item down into view.

    But it does not work when setting visible to false. The loss of visibility takes effect immediately and you do not see the animation. I get a similar problem trying to use States and Transitions instead of Behavior.

    I can't use the Animation's onStopped() signal handler to set visible after the animation is complete, since it has no effect inside a Behavior or a Transition.

    Is there any sensible way to have the visible property set to false only after an animation has finished?



  • I did something similar, you can use SequentialAnimation, then use NumberAnimation (y) and PropertyAction (visible) when going from visible to invisible, and use another SequentialAnimation with PropertyAction and then NumberAnimation when going from invisible to visible.


  • Moderators

    Hi,

    As the item turns off invisible immediately the effect won't be seen obviously.
    You can animate the opacity of the item to have the effect.

    Try the following example,
    @import QtQuick 2.1

    Rectangle {
    id: root
    width: 400
    height: 600
    color: "white"

    Rectangle {
        id: rect
        width: 40
        height: 40
        color: "red"
        state: "1"
        opacity: 0.0
    
        MouseArea {
            anchors.fill: parent
            onClicked: rect.state === "1" ? rect.state = "2" : rect.state = "1"
        }
    
        states: [
            State {
                name: "2"
                PropertyChanges { target: rect; x:root.width-rect.width; y:root.height - rect.height  }
                PropertyChanges { target: rect; opacity: 1.0  }
            }
        ]
    
        transitions: [
            Transition {
                reversible: true
                PropertyAnimation { easing.type: Easing.InOutQuad; properties: "x,y"; duration: 1000 }
                PropertyAnimation { easing.type: Easing.InOutQuad; properties: "opacity"; duration: 1000 }
            }
        ]
    }
    

    }@

    After executing just click on the top-left area as the item is initially positioned there. You will see a gradual animation from top-left to right-bottom.
    May be you could customize the code according to your requirement.



  • Thanks p3c0 and Helbrass.

    Using the opacity makes the item materialise into place out of thin air, like Doctor Who's Tardis. I'm looking for a more mechanical effect, like a shutter coming down when you press a button.

    SequentialAnimation does the job. The trick is that I need to make sure visible is true before the animation. I can then set visible=false as a PropertyChanges in the State, rather than a PropertyAction (which would need an additonal test to check whether to set visible true or false). I only needed one SequentialAnimation. This seems to be the minimum code required.

    @
    states: State {
    name: "hidden"
    PropertyChanges { target: itemId; y: -itemId.height }
    PropertyChanges { target: itemId; visible: false }
    }

            transitions: Transition {
                SequentialAnimation {
                    // make sure the box is always visible before the animation
                    PropertyAction {
                        target: itemId;
                        property: "visible"
                        value: true
                    }
                    PropertyAnimation {
                        target: itemId
                        property: "y"
                    }
                }
            }
    

    @

    I suspect you get a similar effect using a Behavior on a flag variable, e.g. "property bool hidden". But that would be the same concept as using the state variable, so I might as well use the built-in infrastructure.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.