Table of contents
If you’ve ever used QLabel, you might’ve come across one of its methods: QLabel::setMovie, which is very useful for animating its background.
Unfortunately, QWidget does not provide such a method. A limitation that I came across and couldn’t find a solution about it. So I came up with my own solution and felt the need to share it.
Tools:
Implementation:
QMovie could be used by connecting its frameChanged slot to a function that sets QWidget’s palette brush to each frame.
Reimplement:
resizeEvent: so that the background GIF resizes accordingly, to ensure a dynamic layout.
showEvent and hideEvent: to prevent the movie from running when not needed.
Custom QWidget Class:
class MAnimatedBackground : public QWidget
{
Q_OBJECT
public:
QMovie *movie = new QMovie(":/GIFBackground.gif");
QPalette customPalette;
MAnimatedBackground(QWidget *parent = nullptr)
{
//resize the gif to the widget's size
movie->setScaledSize(size());
//I'm using a looping gif and cashing reduced cpu consumption
movie->setCacheMode(QMovie::CacheAll);
//I used a lambda that gets the current frame as a QPixmap
//and used it as the widget palette brush with the window flag
QTimer::connect(movie,&QMovie::frameChanged,[=]()
{
customPalette = palette();
customPalette.setBrush(QPalette::Window, movie->currentPixmap());
setPalette(customPalette);
});
}
protected:
void resizeEvent(QResizeEvent *event)
{
//rescale the gif every time the widget resizes
movie->setScaledSize(size());
}
void showEvent(QShowEvent *event)
{
//start/resume the movie only when the widget is about to show
movie->start();
}
void hideEvent(QHideEvent *event)
{
//pause the movie when the widget hides
movie->setPaused(true);
}
};
Result:
Since QWidget is the most basic widget in Qt Framework — meaning every Qt widget inherits from it — , this could be applied and tweaked in so many ways.
Feel free to suggest improvements and share your thoughts and feedback!