Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to make animated backgrounds?
Forum Updated to NodeBB v4.3 + New Features

How to make animated backgrounds?

Scheduled Pinned Locked Moved Unsolved General and Desktop
24 Posts 6 Posters 2.2k Views 2 Watching
  • 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.
  • artwawA Offline
    artwawA Offline
    artwaw
    wrote on last edited by
    #6

    @Bonnie in theory you can place small QGraphicsView and scene the size of your desired label, attach animated item as a background with the text item on top acting as label. You'll have to give up (or write your own) accelerator routine or onClick handler though.
    Also, the above is for sure an overkill and I can't speak about the performance penalty of such a contraption but in theory that could provide the desired effect...

    For more information please re-read.

    Kind Regards,
    Artur

    M B 2 Replies Last reply
    0
    • artwawA artwaw

      @Bonnie in theory you can place small QGraphicsView and scene the size of your desired label, attach animated item as a background with the text item on top acting as label. You'll have to give up (or write your own) accelerator routine or onClick handler though.
      Also, the above is for sure an overkill and I can't speak about the performance penalty of such a contraption but in theory that could provide the desired effect...

      M Offline
      M Offline
      Mizmas
      wrote on last edited by
      #7

      @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

      B 1 Reply Last reply
      0
      • M Mizmas

        @Bonnie So like mentioned before, that's the problem, you can't place other widgets in QLabel

        B Offline
        B Offline
        Bonnie
        wrote on last edited by Bonnie
        #8

        @Mizmas said in How to make animated backgrounds?:

        @Bonnie So like mentioned before, that's the problem, you can't place other widgets in QLabel

        Actually you can, you just can't do that in the designer.
        QLabel is just a QWidget, it is possible to set layout on it and add child widgets to it.

        1 Reply Last reply
        2
        • artwawA artwaw

          @Bonnie in theory you can place small QGraphicsView and scene the size of your desired label, attach animated item as a background with the text item on top acting as label. You'll have to give up (or write your own) accelerator routine or onClick handler though.
          Also, the above is for sure an overkill and I can't speak about the performance penalty of such a contraption but in theory that could provide the desired effect...

          B Offline
          B Offline
          Bonnie
          wrote on last edited by Bonnie
          #9

          @artwaw If we are talking about handling all the animation by ourselves, sure it is possible.
          You don't even need to use QGraphicsView, just reimplementing QWidget would be enough :)
          But it is so not worth it because we already have QLabel+QMovie that handling all we need.

          1 Reply Last reply
          1
          • M Mizmas

            @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

            B Offline
            B Offline
            Bonnie
            wrote on last edited by
            #10

            @Mizmas said in How to make animated backgrounds?:

            @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

            This is also possible, but not in designer :)

            M 1 Reply Last reply
            0
            • B Bonnie

              @Mizmas said in How to make animated backgrounds?:

              @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

              This is also possible, but not in designer :)

              M Offline
              M Offline
              Mizmas
              wrote on last edited by
              #11

              @Bonnie said in How to make animated backgrounds?:

              @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

              This is also possible, but not in designer :)

              How? I've used QStackedWidget a couple of times only setting the pages with setCurrentIndex (index)

              B 1 Reply Last reply
              0
              • M Mizmas

                @Bonnie said in How to make animated backgrounds?:

                @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

                This is also possible, but not in designer :)

                How? I've used QStackedWidget a couple of times only setting the pages with setCurrentIndex (index)

                B Offline
                B Offline
                Bonnie
                wrote on last edited by
                #12

                @Mizmas said in How to make animated backgrounds?:

                @Bonnie said in How to make animated backgrounds?:

                @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

                This is also possible, but not in designer :)

                How? I've used QStackedWidget a couple of times only setting the pages with setCurrentIndex (index)

                QStackedWidget uses QStackedLayout class to manage child widgets.
                QStackedLayout can set stackingMode to QStackedLayout::StackAll to show all the widgets.
                So just need to get a QLayout * by calling the stackedWidget's layout() method and convert it to QStackedLayout *.

                M 1 Reply Last reply
                3
                • artwawA Offline
                  artwawA Offline
                  artwaw
                  wrote on last edited by
                  #13

                  @Bonnie thanks for the insight, I was not aware. FE is not the area where I play a lot :)
                  I made notes, time to learn new things!

                  For more information please re-read.

                  Kind Regards,
                  Artur

                  1 Reply Last reply
                  1
                  • B Bonnie

                    @Mizmas said in How to make animated backgrounds?:

                    @Bonnie said in How to make animated backgrounds?:

                    @artwaw I haven't tried it yet, but would it be possible to use a QStackedWidget, have the QLabel in one page, and the QFrame widget on another page. Could you then display both pages at the same time?

                    This is also possible, but not in designer :)

                    How? I've used QStackedWidget a couple of times only setting the pages with setCurrentIndex (index)

                    QStackedWidget uses QStackedLayout class to manage child widgets.
                    QStackedLayout can set stackingMode to QStackedLayout::StackAll to show all the widgets.
                    So just need to get a QLayout * by calling the stackedWidget's layout() method and convert it to QStackedLayout *.

                    M Offline
                    M Offline
                    Mizmas
                    wrote on last edited by
                    #14

                    @Bonnie Thanks for all the tips, I've tried it with a random gif in a stacked widget and it works with your method.
                    python_VpYj91G8im-ezgif.com-video-to-gif-converter (1).gif

                    If anyone finds this thread in the future I did it like this:

                            self.your_stacked_widget = self.findChild(QStackedWidget, 'your_stacked_widget')
                            self.background_label = self.findChild(QLabel, 'background_label')
                    
                            movie = QMovie(":/your_gif.gif")
                            movie.setScaledSize(self.your_stacked_widget.size())
                            self.background_label.setMovie(movie)
                            movie.start()
                    
                            if self.your_stacked_widget:
                                # Get the QLayout from the stacked widget and cast it to QStackedLayout
                                self.stackedLayout = self.your_stacked_widget.layout()
                    
                                if isinstance(self.stackedLayout, QStackedLayout):
                                    # Set the stacking mode to StackAll to show all widgets
                                    self.stackedLayout.setStackingMode(QStackedLayout.StackingMode.StackAll)
                    

                    Would this be most straightforward method if you want to lay everything out in QT Designer?

                    Pl45m4P B 2 Replies Last reply
                    4
                    • M Mizmas

                      @Bonnie Thanks for all the tips, I've tried it with a random gif in a stacked widget and it works with your method.
                      python_VpYj91G8im-ezgif.com-video-to-gif-converter (1).gif

                      If anyone finds this thread in the future I did it like this:

                              self.your_stacked_widget = self.findChild(QStackedWidget, 'your_stacked_widget')
                              self.background_label = self.findChild(QLabel, 'background_label')
                      
                              movie = QMovie(":/your_gif.gif")
                              movie.setScaledSize(self.your_stacked_widget.size())
                              self.background_label.setMovie(movie)
                              movie.start()
                      
                              if self.your_stacked_widget:
                                  # Get the QLayout from the stacked widget and cast it to QStackedLayout
                                  self.stackedLayout = self.your_stacked_widget.layout()
                      
                                  if isinstance(self.stackedLayout, QStackedLayout):
                                      # Set the stacking mode to StackAll to show all widgets
                                      self.stackedLayout.setStackingMode(QStackedLayout.StackingMode.StackAll)
                      

                      Would this be most straightforward method if you want to lay everything out in QT Designer?

                      Pl45m4P Offline
                      Pl45m4P Offline
                      Pl45m4
                      wrote on last edited by
                      #15

                      @Mizmas

                      LOL that looks hilarious :D
                      Didn't know that it was possible. Also thanks to @Bonnie


                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      1 Reply Last reply
                      0
                      • M Mizmas

                        @Bonnie Thanks for all the tips, I've tried it with a random gif in a stacked widget and it works with your method.
                        python_VpYj91G8im-ezgif.com-video-to-gif-converter (1).gif

                        If anyone finds this thread in the future I did it like this:

                                self.your_stacked_widget = self.findChild(QStackedWidget, 'your_stacked_widget')
                                self.background_label = self.findChild(QLabel, 'background_label')
                        
                                movie = QMovie(":/your_gif.gif")
                                movie.setScaledSize(self.your_stacked_widget.size())
                                self.background_label.setMovie(movie)
                                movie.start()
                        
                                if self.your_stacked_widget:
                                    # Get the QLayout from the stacked widget and cast it to QStackedLayout
                                    self.stackedLayout = self.your_stacked_widget.layout()
                        
                                    if isinstance(self.stackedLayout, QStackedLayout):
                                        # Set the stacking mode to StackAll to show all widgets
                                        self.stackedLayout.setStackingMode(QStackedLayout.StackingMode.StackAll)
                        

                        Would this be most straightforward method if you want to lay everything out in QT Designer?

                        B Offline
                        B Offline
                        Bonnie
                        wrote on last edited by Bonnie
                        #16

                        @Mizmas said in How to make animated backgrounds?:

                        Would this be most straightforward method if you want to lay everything out in QT Designer?

                        I have another approach, but I don't know how to do that in PyQt, so I'll just show it in C++.
                        To make a widget in designer still acting like a QWidget/QFrame, but actually being a QLabel, we can use promoting.
                        (In case anyone don't know about promoting widgets, here's the documentation: https://doc.qt.io/qt-6/designer-using-custom-widgets.html#promoting-widgets)
                        So right click the background widget and select "Promote to ...".
                        It would be great if we can promote it to QLabel directly, sadly designer doesn't allow that, so we promote it to a custom class name, say "QLabelWidget" with the header file "qlabelwidget.h".
                        Then create "qlabelwidget.h" with below content:

                        #ifndef QLABELWIDGET_H
                        #define QLABELWIDGET_H
                        #include <QLabel>
                        typedef QLabel QLabelWidget;
                        #endif // QLABELWIDGET_H
                        

                        So the background widget will become a QLabelWidget, aka QLabel. You cannot edit its QLabel properties in the designer, but it can call QLabel member functions in the code. Since QMovie can only be set in the code, I think that's not a problem.

                        M 1 Reply Last reply
                        3
                        • B Bonnie

                          @Mizmas said in How to make animated backgrounds?:

                          Would this be most straightforward method if you want to lay everything out in QT Designer?

                          I have another approach, but I don't know how to do that in PyQt, so I'll just show it in C++.
                          To make a widget in designer still acting like a QWidget/QFrame, but actually being a QLabel, we can use promoting.
                          (In case anyone don't know about promoting widgets, here's the documentation: https://doc.qt.io/qt-6/designer-using-custom-widgets.html#promoting-widgets)
                          So right click the background widget and select "Promote to ...".
                          It would be great if we can promote it to QLabel directly, sadly designer doesn't allow that, so we promote it to a custom class name, say "QLabelWidget" with the header file "qlabelwidget.h".
                          Then create "qlabelwidget.h" with below content:

                          #ifndef QLABELWIDGET_H
                          #define QLABELWIDGET_H
                          #include <QLabel>
                          typedef QLabel QLabelWidget;
                          #endif // QLABELWIDGET_H
                          

                          So the background widget will become a QLabelWidget, aka QLabel. You cannot edit its QLabel properties in the designer, but it can call QLabel member functions in the code. Since QMovie can only be set in the code, I think that's not a problem.

                          M Offline
                          M Offline
                          Mizmas
                          wrote on last edited by
                          #17

                          @Bonnie Yes, that's definitely more straight forward, thanks again :D

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            Mizmas
                            wrote on last edited by
                            #18

                            I've been experimenting some more with gif backgrounds, subclassing a QFrame using QLabel.
                            I tried making a background for a push button, and the background gif changes based whether the cursor is hovering over the button or not.
                            This is what I have so far: https://streamable.com/k02xqk

                            # set initial state for website button
                                self.website_button_frame = self.findChild(GifFrame, 'website_button_frame')
                                self.gif = QMovie(':/animations/website_logo.gif')
                                self.gif.setScaledSize(self.website_button_frame.size())
                                self.website_button_frame.setMovie(self.gif)
                                self.gif.start()
                                
                                # Install an event filter on the website button
                                self.website_button.installEventFilter(self)
                            
                            # website_button hover/not hover filter
                            def eventFilter(self, watched, event):
                                if watched == self.website_button:
                                    if event.type() == QEvent.Type.Enter:
                                        # Action when hovering
                                        gif = QMovie(":/animations/website_logo_purple.gif")
                                        gif.setScaledSize(self.website_button_frame.size())
                                        self.website_button_frame.setMovie(gif)
                                        gif.start()
                                    elif event.type() == QEvent.Type.Leave:
                                        # Action when not hovering
                                        gif = QMovie(":/animations/website_logo.gif")
                                        gif.setScaledSize(self.website_button_frame.size())
                                        self.website_button_frame.setMovie(gif)
                                        gif.start()
                                return super().eventFilter(watched, event)
                            

                            Basically, I'm using two gifs with two different colors, they both have transparent backgrounds and solid color objects. I'm using an event filter to change the two, based on whether the cursor is hovering over the button or not. The problem is that this transition is not smooth and jittery. This is because both the QMovie objects start over again from the start and not on the frame that was displayed before. I've tried using methods of the QMovie like currentFrameNumber() and jumpToFrame(), but they only seem to work if you're using the same QMovie (at least I couldn't get it to work).

                            Is there some approach I can take to work with a single .gif file, and somehow programmatically change the color of the solid color objects while the gif is playing? Or is there some different stuff I can try, maybe outside of QT?

                            1 Reply Last reply
                            0
                            • GrecKoG Offline
                              GrecKoG Offline
                              GrecKo
                              Qt Champions 2018
                              wrote on last edited by GrecKo
                              #19

                              There is some different stuff you can try, inside Qt. Namely Qt Quick.
                              In my opinion it is much more suited to the kind of application you appear to make.
                              QtQuick.Effects's MultiEffect can color any abritrary item

                              For fun I tried to recreate the stuff you showed in QML with Qt Quick, here's the quick and a bit ugly code:

                              import QtQuick
                              import QtQuick.Controls
                              import QtQuick.Effects
                              
                              ApplicationWindow {
                                  id: window
                                  width: 640
                                  height: 480
                                  visible: true
                              
                                  property real radius: 8
                              
                                  flags: Qt.FramelessWindowHint
                                  color: "transparent"
                              
                                  Rectangle {
                                      parent: window.contentItem.parent
                                      z: -1
                                      anchors.fill: parent
                                      color: "#F7BF8A"
                                      radius: window.radius
                                      border.width: 1
                                  }
                                  footer: Rectangle {
                                      color: "#B1C368"
                                      height: 50
                                      topLeftRadius: 0
                                      topRightRadius: 0
                                      bottomLeftRadius: window.radius
                                      bottomRightRadius: window.radius
                                      border.width: 1
                                      Text {
                                          id: siteLink
                                          anchors {
                                              verticalCenter: parent.verticalCenter
                                              right: parent.right
                                              rightMargin: 20
                                          }
                                          text: "By midimagic"
                                          font.family: "Courier New"
                                          color: hoverHandler.hovered ? "#8D7BDE" : "black"
                              
                                          HoverHandler {
                                              id: hoverHandler
                                              cursorShape: Qt.PointingHandCursor
                                          }
                                          TapHandler {
                                              onTapped: Qt.openUrlExternally("https://forum.qt.io")
                                          }
                                          AnimatedImage {
                                              id: siteGif
                                              visible: false
                                              anchors {
                                                  fill: parent
                                                  margins: -15
                                              }
                                              source: "https://emoji.discadia.com/emojis/d3897e57-3a33-4136-a6bb-882343233261.gif"
                                              fillMode: Image.PreserveAspectFit
                                          }
                                          MultiEffect {
                                              anchors.fill: siteGif
                                              source: siteGif
                                              colorizationColor: siteLink.color
                                              colorization: 1
                                          }
                                      }
                                  }
                              }
                              

                              Here's the result: ( the sluggyness is only in the recording, it runs smooth)
                              colored background gif

                              M 1 Reply Last reply
                              0
                              • GrecKoG GrecKo

                                There is some different stuff you can try, inside Qt. Namely Qt Quick.
                                In my opinion it is much more suited to the kind of application you appear to make.
                                QtQuick.Effects's MultiEffect can color any abritrary item

                                For fun I tried to recreate the stuff you showed in QML with Qt Quick, here's the quick and a bit ugly code:

                                import QtQuick
                                import QtQuick.Controls
                                import QtQuick.Effects
                                
                                ApplicationWindow {
                                    id: window
                                    width: 640
                                    height: 480
                                    visible: true
                                
                                    property real radius: 8
                                
                                    flags: Qt.FramelessWindowHint
                                    color: "transparent"
                                
                                    Rectangle {
                                        parent: window.contentItem.parent
                                        z: -1
                                        anchors.fill: parent
                                        color: "#F7BF8A"
                                        radius: window.radius
                                        border.width: 1
                                    }
                                    footer: Rectangle {
                                        color: "#B1C368"
                                        height: 50
                                        topLeftRadius: 0
                                        topRightRadius: 0
                                        bottomLeftRadius: window.radius
                                        bottomRightRadius: window.radius
                                        border.width: 1
                                        Text {
                                            id: siteLink
                                            anchors {
                                                verticalCenter: parent.verticalCenter
                                                right: parent.right
                                                rightMargin: 20
                                            }
                                            text: "By midimagic"
                                            font.family: "Courier New"
                                            color: hoverHandler.hovered ? "#8D7BDE" : "black"
                                
                                            HoverHandler {
                                                id: hoverHandler
                                                cursorShape: Qt.PointingHandCursor
                                            }
                                            TapHandler {
                                                onTapped: Qt.openUrlExternally("https://forum.qt.io")
                                            }
                                            AnimatedImage {
                                                id: siteGif
                                                visible: false
                                                anchors {
                                                    fill: parent
                                                    margins: -15
                                                }
                                                source: "https://emoji.discadia.com/emojis/d3897e57-3a33-4136-a6bb-882343233261.gif"
                                                fillMode: Image.PreserveAspectFit
                                            }
                                            MultiEffect {
                                                anchors.fill: siteGif
                                                source: siteGif
                                                colorizationColor: siteLink.color
                                                colorization: 1
                                            }
                                        }
                                    }
                                }
                                

                                Here's the result: ( the sluggyness is only in the recording, it runs smooth)
                                colored background gif

                                M Offline
                                M Offline
                                Mizmas
                                wrote on last edited by Mizmas
                                #20

                                @GrecKo Damn :D I've never used QT Quick before, but thank you so much

                                1 Reply Last reply
                                0
                                • GrecKoG Offline
                                  GrecKoG Offline
                                  GrecKo
                                  Qt Champions 2018
                                  wrote on last edited by
                                  #21

                                  Alternatively if you want to stick with QWidgets you could retrieve the current frame number of the running QMovie and set it to the new one when switching. With currentFrameNumber and jumpToFrame.

                                  M 2 Replies Last reply
                                  0
                                  • GrecKoG GrecKo

                                    Alternatively if you want to stick with QWidgets you could retrieve the current frame number of the running QMovie and set it to the new one when switching. With currentFrameNumber and jumpToFrame.

                                    M Offline
                                    M Offline
                                    Mizmas
                                    wrote on last edited by
                                    #22

                                    @GrecKo Yeah I've tried again using currentFrameNumber() and jumpToFrame() and it seems to work, I must've messed something up before. Thanks again

                                    1 Reply Last reply
                                    0
                                    • GrecKoG GrecKo

                                      Alternatively if you want to stick with QWidgets you could retrieve the current frame number of the running QMovie and set it to the new one when switching. With currentFrameNumber and jumpToFrame.

                                      M Offline
                                      M Offline
                                      Mizmas
                                      wrote on last edited by
                                      #23

                                      @GrecKo Though, there are times where the gifs begin to lag and slow down for a moment, even when the cursor is not interacting with them. This happens on all other QMovie objects with gifs that I've tried, even if there's no cursor interaction coded

                                      artwawA 1 Reply Last reply
                                      0
                                      • M Mizmas

                                        @GrecKo Though, there are times where the gifs begin to lag and slow down for a moment, even when the cursor is not interacting with them. This happens on all other QMovie objects with gifs that I've tried, even if there's no cursor interaction coded

                                        artwawA Offline
                                        artwawA Offline
                                        artwaw
                                        wrote on last edited by
                                        #24

                                        @Mizmas please check the release version of your program, the debug ones can be laggy for obvious reasons.

                                        For more information please re-read.

                                        Kind Regards,
                                        Artur

                                        1 Reply Last reply
                                        0

                                        • Login

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