Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Generalizing Animation Setup in QML
QtWS25 Last Chance

Generalizing Animation Setup in QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
animationsqml qml
8 Posts 3 Posters 762 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    Veltroniv
    wrote on last edited by
    #1

    I've been tinkering with animations in QML lately and wondering if there's a more streamlined way to set them up. Specifically, I find myself declaring PropertyAnimations for various elements individually, and it feels a bit repetitive.

    For instance, let's say I'm setting up opacity animations for different elements (same animation, for various elements in different time). Currently, I'm creating separate PropertyAnimation blocks for each element:

      PropertyAnimation {
        id: changeOpacity1
        target: passwordRequirement1
        property: "opacity"
        from: passwordRequirement1.opacity 
        to: passwordRequirement1.opacity === 1 ? 0 : 1 
        duration: 500
      }
    
      PropertyAnimation {
        id: changeOpacity2
        target: passwordRequirement2
        property: "opacity"
        from: passwordRequirement2.opacity 
        to: passwordRequirement2.opacity === 1 ? 0 : 1 
        duration: 500
      }
    
      PropertyAnimation {
        id: changeOpacity3
        target: passwordRequirement3
        property: "opacity"
        from: passwordRequirement3.opacity 
        to: passwordRequirement3.opacity === 1 ? 0 : 1 
        duration: 500
      }
    

    However, I'm wondering if there's a more generalized approach. Maybe something like a function createAnimation where I could pass the target element and property as arguments? This way, I wouldn't have to repeat the animation setup logic for each element. Thank u!

    A 1 Reply Last reply
    1
    • V Veltroniv

      I've been tinkering with animations in QML lately and wondering if there's a more streamlined way to set them up. Specifically, I find myself declaring PropertyAnimations for various elements individually, and it feels a bit repetitive.

      For instance, let's say I'm setting up opacity animations for different elements (same animation, for various elements in different time). Currently, I'm creating separate PropertyAnimation blocks for each element:

        PropertyAnimation {
          id: changeOpacity1
          target: passwordRequirement1
          property: "opacity"
          from: passwordRequirement1.opacity 
          to: passwordRequirement1.opacity === 1 ? 0 : 1 
          duration: 500
        }
      
        PropertyAnimation {
          id: changeOpacity2
          target: passwordRequirement2
          property: "opacity"
          from: passwordRequirement2.opacity 
          to: passwordRequirement2.opacity === 1 ? 0 : 1 
          duration: 500
        }
      
        PropertyAnimation {
          id: changeOpacity3
          target: passwordRequirement3
          property: "opacity"
          from: passwordRequirement3.opacity 
          to: passwordRequirement3.opacity === 1 ? 0 : 1 
          duration: 500
        }
      

      However, I'm wondering if there's a more generalized approach. Maybe something like a function createAnimation where I could pass the target element and property as arguments? This way, I wouldn't have to repeat the animation setup logic for each element. Thank u!

      A Offline
      A Offline
      afalsa
      wrote on last edited by
      #2

      @Veltroniv

      Hello!

      You could create a PasswordRequerimentBase with all common properties and then create your custom PasswordRequerimentXX.

      In this way you only has to write one Property Animation

      V 1 Reply Last reply
      0
      • A afalsa

        @Veltroniv

        Hello!

        You could create a PasswordRequerimentBase with all common properties and then create your custom PasswordRequerimentXX.

        In this way you only has to write one Property Animation

        V Offline
        V Offline
        Veltroniv
        wrote on last edited by
        #3

        @afalsa
        Sorry i dont get it ;/

          PasswordRequirement {
            id: passwordRequirement1
            anchors.left: usernameTextField.left
            anchors.top: dummyRec2.bottom
            text: "Password should be at least 8 characters long."
            opacity: 0
          }
        
          PasswordRequirement {
            id: passwordRequirement2
            anchors.left: usernameTextField.left
            anchors.top: passwordRequirement1.bottom
            text: "Password should contain at least one special character."
            opacity: 0
          }
        
          PasswordRequirement {
            id: passwordRequirement3
            anchors.left: usernameTextField.left
            anchors.top: passwordRequirement2.bottom
            text: "Password should contain at least one uppercase letter."
            opacity: 0
          }
        

        I have a custom Password Requirement component, so I suppose it serves as a base. What should I do next? Should I specify only one property animation and somehow change the target dynamically? Could you please provide an example? Also, what if an animation on a different target starts playing while the previous one hasn't stopped animating the property yet?

        GrecKoG A 2 Replies Last reply
        0
        • V Veltroniv

          @afalsa
          Sorry i dont get it ;/

            PasswordRequirement {
              id: passwordRequirement1
              anchors.left: usernameTextField.left
              anchors.top: dummyRec2.bottom
              text: "Password should be at least 8 characters long."
              opacity: 0
            }
          
            PasswordRequirement {
              id: passwordRequirement2
              anchors.left: usernameTextField.left
              anchors.top: passwordRequirement1.bottom
              text: "Password should contain at least one special character."
              opacity: 0
            }
          
            PasswordRequirement {
              id: passwordRequirement3
              anchors.left: usernameTextField.left
              anchors.top: passwordRequirement2.bottom
              text: "Password should contain at least one uppercase letter."
              opacity: 0
            }
          

          I have a custom Password Requirement component, so I suppose it serves as a base. What should I do next? Should I specify only one property animation and somehow change the target dynamically? Could you please provide an example? Also, what if an animation on a different target starts playing while the previous one hasn't stopped animating the property yet?

          GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #4

          @Veltroniv How do you want your animations to be triggered?

          I've shared some prewritten animations to be used as Behavior here : https://github.com/oKcerG/QuickBehaviors/

          1 Reply Last reply
          1
          • V Veltroniv

            @afalsa
            Sorry i dont get it ;/

              PasswordRequirement {
                id: passwordRequirement1
                anchors.left: usernameTextField.left
                anchors.top: dummyRec2.bottom
                text: "Password should be at least 8 characters long."
                opacity: 0
              }
            
              PasswordRequirement {
                id: passwordRequirement2
                anchors.left: usernameTextField.left
                anchors.top: passwordRequirement1.bottom
                text: "Password should contain at least one special character."
                opacity: 0
              }
            
              PasswordRequirement {
                id: passwordRequirement3
                anchors.left: usernameTextField.left
                anchors.top: passwordRequirement2.bottom
                text: "Password should contain at least one uppercase letter."
                opacity: 0
              }
            

            I have a custom Password Requirement component, so I suppose it serves as a base. What should I do next? Should I specify only one property animation and somehow change the target dynamically? Could you please provide an example? Also, what if an animation on a different target starts playing while the previous one hasn't stopped animating the property yet?

            A Offline
            A Offline
            afalsa
            wrote on last edited by afalsa
            #5

            @Veltroniv

            Hello!

            I agree with @GrecKo , how do you want your animations to start? Do you only want one running at a time?

            Here is an example of what I understood you needed:

            You define your base component with everything you want it to share:

            // BaseComponent.qml
            import QtQuick 2.15
            import QtQuick.Controls 2.15
            
            Rectangle {
            
                id: root
                implicitHeight: base.implicitHeight
                implicitWidth: base.implicitWidth
            
                color: "transparent"
                border.color: "red"
                opacity: 0
            
                property alias text: base.text
            
                Label {
                    id: base
                    anchors.fill: parent
            
                    color: "black"
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
            
                Behavior on opacity {
                    NumberAnimation {
                        duration: 1000
                    }
                }
            }
            

            You create your base component as many times as you want:

            import QtQuick 2.15
            import QtQuick.Controls 2.15
            
            Item {
                width: 500
                height: 500
            
                Column {
                    id: container
                    anchors.fill: parent
                    anchors.margins: 64
            
                    property int showComponent: -1
            
                    Button {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                        text: "Change item visible"
            
                        onClicked: {
                            container.showComponent++
            
                            if (container.showComponent === 3) {
                                container.showComponent = 0
                            }
                        }
                    }
            
                    BaseComponent {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                        text: "Password should be at least 8 characters long."
                        opacity: container.showComponent === 0 ? 1 : 0
                    }
                    BaseComponent {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                        text: "Password should contain at least one special character."
                        opacity: container.showComponent === 1 ? 1 : 0
                    }
                    BaseComponent {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                        text: "Password should contain at least one uppercase letter."
                        opacity: container.showComponent === 2 ? 1 : 0
                    }
                }
            }
            

            Or even if you want to avoid more duplicate code you can still use inline components:

            import QtQuick 2.15
            import QtQuick.Controls 2.15
            
            Item {
                width: 500
                height: 500
            
                component BaseComponentInline: BaseComponent {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    height: 80
                }
            
                Column {
                    id: container
                    anchors.fill: parent
                    anchors.margins: 64
            
                    property int showComponent: -1
            
                    Button {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                        text: "Change item visible"
            
                        onClicked: {
                            container.showComponent++
            
                            if (container.showComponent === 3) {
                                container.showComponent = 0
                            }
                        }
                    }
            
                    BaseComponentInline {
                        text: "Password should be at least 8 characters long."
                        opacity: container.showComponent === 0 ? 1 : 0
                    }
                    BaseComponentInline {
                        text: "Password should contain at least one special character."
                        opacity: container.showComponent === 1 ? 1 : 0
                    }
                    BaseComponentInline {
                        text: "Password should contain at least one uppercase letter."
                        opacity: container.showComponent === 2 ? 1 : 0
                    }
                }
            }
            
            V 1 Reply Last reply
            1
            • A afalsa

              @Veltroniv

              Hello!

              I agree with @GrecKo , how do you want your animations to start? Do you only want one running at a time?

              Here is an example of what I understood you needed:

              You define your base component with everything you want it to share:

              // BaseComponent.qml
              import QtQuick 2.15
              import QtQuick.Controls 2.15
              
              Rectangle {
              
                  id: root
                  implicitHeight: base.implicitHeight
                  implicitWidth: base.implicitWidth
              
                  color: "transparent"
                  border.color: "red"
                  opacity: 0
              
                  property alias text: base.text
              
                  Label {
                      id: base
                      anchors.fill: parent
              
                      color: "black"
                      horizontalAlignment: Text.AlignHCenter
                      verticalAlignment: Text.AlignVCenter
                  }
              
                  Behavior on opacity {
                      NumberAnimation {
                          duration: 1000
                      }
                  }
              }
              

              You create your base component as many times as you want:

              import QtQuick 2.15
              import QtQuick.Controls 2.15
              
              Item {
                  width: 500
                  height: 500
              
                  Column {
                      id: container
                      anchors.fill: parent
                      anchors.margins: 64
              
                      property int showComponent: -1
              
                      Button {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                          text: "Change item visible"
              
                          onClicked: {
                              container.showComponent++
              
                              if (container.showComponent === 3) {
                                  container.showComponent = 0
                              }
                          }
                      }
              
                      BaseComponent {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                          text: "Password should be at least 8 characters long."
                          opacity: container.showComponent === 0 ? 1 : 0
                      }
                      BaseComponent {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                          text: "Password should contain at least one special character."
                          opacity: container.showComponent === 1 ? 1 : 0
                      }
                      BaseComponent {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                          text: "Password should contain at least one uppercase letter."
                          opacity: container.showComponent === 2 ? 1 : 0
                      }
                  }
              }
              

              Or even if you want to avoid more duplicate code you can still use inline components:

              import QtQuick 2.15
              import QtQuick.Controls 2.15
              
              Item {
                  width: 500
                  height: 500
              
                  component BaseComponentInline: BaseComponent {
                      anchors.left: parent.left
                      anchors.right: parent.right
                      height: 80
                  }
              
                  Column {
                      id: container
                      anchors.fill: parent
                      anchors.margins: 64
              
                      property int showComponent: -1
              
                      Button {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                          text: "Change item visible"
              
                          onClicked: {
                              container.showComponent++
              
                              if (container.showComponent === 3) {
                                  container.showComponent = 0
                              }
                          }
                      }
              
                      BaseComponentInline {
                          text: "Password should be at least 8 characters long."
                          opacity: container.showComponent === 0 ? 1 : 0
                      }
                      BaseComponentInline {
                          text: "Password should contain at least one special character."
                          opacity: container.showComponent === 1 ? 1 : 0
                      }
                      BaseComponentInline {
                          text: "Password should contain at least one uppercase letter."
                          opacity: container.showComponent === 2 ? 1 : 0
                      }
                  }
              }
              
              V Offline
              V Offline
              Veltroniv
              wrote on last edited by
              #6

              @afalsa Thank u so much! it helps me a lot. Now im dealing with last thing.

                states: [
                  State {
                    name: "upConfirmPassword"
              
                    AnchorChanges {
                      target: confirmPasswordTextField
                      anchors.top: dummyRec2.bottom
                    }
                    PropertyChanges {
                      target: passwordRequirement1
                      opacity: 0
                    }
                    PropertyChanges {
                      target: passwordRequirement2
                      opacity: 0
                    }
                    PropertyChanges {
                      target: passwordRequirement3
                      opacity: 0
                    }
                    PropertyChanges {
                      target: passwordRequirement4
                      opacity: 0
                    }
                  },
                  State {
                    name: "downConfirmPassword"
                    AnchorChanges {
                      target: confirmPasswordTextField
                      anchors.top: dummyRec3.bottom
                    }
                    PropertyChanges {
                      target: passwordRequirement1
                      opacity: 1
                    }
                    PropertyChanges {
                      target: passwordRequirement2
                      opacity: 1
                    }
                    PropertyChanges {
                      target: passwordRequirement3
                      opacity: 1
                    }
                    PropertyChanges {
                      target: passwordRequirement4
                      opacity: 1
                    }
                  },
                  State {
                    name: "upEmailAddress"
              
                    AnchorChanges {
                      target: emailAddressTextField
                      anchors.top: dummyRec4.bottom
                    }
                    PropertyChanges {
                      target: passwordRequirement5
                      opacity: 0
                    }
                  },
                  State {
                    name: "downEmailAddress"
                    AnchorChanges {
                      target: emailAddressTextField
                      anchors.top: dummyRec5.bottom
                    }
              
                    PropertyChanges {
                      target: passwordRequirement5
                      opacity: 1
                    }
                  }
                ]
              

              is any option to set up targets: [] or make this solution more "cleaner" or it is what it is ? :D

              A 1 Reply Last reply
              0
              • V Veltroniv

                @afalsa Thank u so much! it helps me a lot. Now im dealing with last thing.

                  states: [
                    State {
                      name: "upConfirmPassword"
                
                      AnchorChanges {
                        target: confirmPasswordTextField
                        anchors.top: dummyRec2.bottom
                      }
                      PropertyChanges {
                        target: passwordRequirement1
                        opacity: 0
                      }
                      PropertyChanges {
                        target: passwordRequirement2
                        opacity: 0
                      }
                      PropertyChanges {
                        target: passwordRequirement3
                        opacity: 0
                      }
                      PropertyChanges {
                        target: passwordRequirement4
                        opacity: 0
                      }
                    },
                    State {
                      name: "downConfirmPassword"
                      AnchorChanges {
                        target: confirmPasswordTextField
                        anchors.top: dummyRec3.bottom
                      }
                      PropertyChanges {
                        target: passwordRequirement1
                        opacity: 1
                      }
                      PropertyChanges {
                        target: passwordRequirement2
                        opacity: 1
                      }
                      PropertyChanges {
                        target: passwordRequirement3
                        opacity: 1
                      }
                      PropertyChanges {
                        target: passwordRequirement4
                        opacity: 1
                      }
                    },
                    State {
                      name: "upEmailAddress"
                
                      AnchorChanges {
                        target: emailAddressTextField
                        anchors.top: dummyRec4.bottom
                      }
                      PropertyChanges {
                        target: passwordRequirement5
                        opacity: 0
                      }
                    },
                    State {
                      name: "downEmailAddress"
                      AnchorChanges {
                        target: emailAddressTextField
                        anchors.top: dummyRec5.bottom
                      }
                
                      PropertyChanges {
                        target: passwordRequirement5
                        opacity: 1
                      }
                    }
                  ]
                

                is any option to set up targets: [] or make this solution more "cleaner" or it is what it is ? :D

                A Offline
                A Offline
                afalsa
                wrote on last edited by
                #7

                @Veltroniv

                Hello!

                I dont get what you mean with "set up targets". I don't know of a better way to make that cleaner, the only thing I can think of is to group all the PropertyChanges into one. Coming back to my example:

                import QtQuick 2.15
                import QtQuick.Controls 2.15
                
                Item {
                    id: root
                    width: 500
                    height: 500
                
                    component BaseComponentInline: BaseComponent {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        height: 80
                    }
                
                    Column {
                        id: container
                        anchors.fill: parent
                        anchors.margins: 64
                
                        property int showComponent: -1
                
                        Button {
                            anchors.left: parent.left
                            anchors.right: parent.right
                            height: 80
                            text: "Change item visible"
                
                            onClicked: {
                
                                if (root.state === "upConfirmPassword") {
                                    root.state = "downConfirmPassword"
                                } else {
                                    root.state = "upConfirmPassword"
                                }
                            }
                        }
                
                        BaseComponentInline {
                            id: passwordRequeriment1
                            text: "Password should be at least 8 characters long."
                        }
                        BaseComponentInline {
                            id: passwordRequeriment2
                            text: "Password should contain at least one special character."
                        }
                        BaseComponentInline {
                            id: passwordRequeriment3
                            text: "Password should contain at least one uppercase letter."
                        }
                    }
                
                    state: "upConfirmPassword"
                
                    states: [
                        State {
                            name: "upConfirmPassword"
                            PropertyChanges {
                                passwordRequeriment1.opacity: 0
                                passwordRequeriment2.opacity: 0
                                passwordRequeriment3.opacity: 0
                            }
                        },
                        State {
                            name: "downConfirmPassword"
                            PropertyChanges {
                                passwordRequeriment1.opacity: 1
                                passwordRequeriment2.opacity: 1
                                passwordRequeriment3.opacity: 1
                            }
                        }
                    ]
                }
                
                
                V 1 Reply Last reply
                0
                • A afalsa

                  @Veltroniv

                  Hello!

                  I dont get what you mean with "set up targets". I don't know of a better way to make that cleaner, the only thing I can think of is to group all the PropertyChanges into one. Coming back to my example:

                  import QtQuick 2.15
                  import QtQuick.Controls 2.15
                  
                  Item {
                      id: root
                      width: 500
                      height: 500
                  
                      component BaseComponentInline: BaseComponent {
                          anchors.left: parent.left
                          anchors.right: parent.right
                          height: 80
                      }
                  
                      Column {
                          id: container
                          anchors.fill: parent
                          anchors.margins: 64
                  
                          property int showComponent: -1
                  
                          Button {
                              anchors.left: parent.left
                              anchors.right: parent.right
                              height: 80
                              text: "Change item visible"
                  
                              onClicked: {
                  
                                  if (root.state === "upConfirmPassword") {
                                      root.state = "downConfirmPassword"
                                  } else {
                                      root.state = "upConfirmPassword"
                                  }
                              }
                          }
                  
                          BaseComponentInline {
                              id: passwordRequeriment1
                              text: "Password should be at least 8 characters long."
                          }
                          BaseComponentInline {
                              id: passwordRequeriment2
                              text: "Password should contain at least one special character."
                          }
                          BaseComponentInline {
                              id: passwordRequeriment3
                              text: "Password should contain at least one uppercase letter."
                          }
                      }
                  
                      state: "upConfirmPassword"
                  
                      states: [
                          State {
                              name: "upConfirmPassword"
                              PropertyChanges {
                                  passwordRequeriment1.opacity: 0
                                  passwordRequeriment2.opacity: 0
                                  passwordRequeriment3.opacity: 0
                              }
                          },
                          State {
                              name: "downConfirmPassword"
                              PropertyChanges {
                                  passwordRequeriment1.opacity: 1
                                  passwordRequeriment2.opacity: 1
                                  passwordRequeriment3.opacity: 1
                              }
                          }
                      ]
                  }
                  
                  
                  V Offline
                  V Offline
                  Veltroniv
                  wrote on last edited by
                  #8

                  @afalsa said in Generalizing Animation Setup in QML:

                        PropertyChanges {
                              passwordRequeriment1.opacity: 0
                              passwordRequeriment2.opacity: 0
                              passwordRequeriment3.opacity: 0
                          }
                  

                  Thanks ! Work excellent!

                  1 Reply Last reply
                  1
                  • V Veltroniv has marked this topic as solved on

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved