How to set animated icon to QPushButton in Qt5?

This can be accomplished without subclassing QPushButton by simply using the signal / slot mechanism of Qt. Connect the frameChanged signal of QMovie to a custom slot in the class that contains this QPushButton. This function will apply the current frame of the QMovie as the icon of the QPushButton. It should look something like this:

// member function that catches the frameChanged signal of the QMovie
void MyWidget::setButtonIcon(int frame)
{
    myPushButton->setIcon(QIcon(myMovie->currentPixmap()));
}

And when allocating your QMovie and QPushButton members ...

myPushButton = new QPushButton();
myMovie = new QMovie("someAnimation.gif");

connect(myMovie,SIGNAL(frameChanged(int)),this,SLOT(setButtonIcon(int)));

// if movie doesn't loop forever, force it to.
if (myMovie->loopCount() != -1)
    connect(myMovie,SIGNAL(finished()),myMovie,SLOT(start()));

myMovie->start();

Since I had to solve this problem for a project of mine today, I just wanted to drop the solution I found for future people, because this question has lots of views and I considered the solution quite elegant. The solution was posted here. It sets the icon of the pushButton every time, the frame of the QMovie changes:

auto movie = new QMovie(this);
movie->setFileName(":/sample.gif");
connect(movie, &QMovie::frameChanged, [=]{
  pushButton->setIcon(movie->currentPixmap());
});
movie->start();

This also has the advantage, that the icon will not appear, until the QMovie was started. Here is also the python solution, I derived for my project:

#'hide' the icon on the pushButton
pushButton.setIcon(QIcon())
animated_spinner = QtGui.QMovie(":/icons/images/loader.gif")
animated_spinner.frameChanged.connect(updateSpinnerAniamation)           

def updateSpinnerAniamation(self):
  #'hide' the text of the button
  pushButton.setText("")
  pushButton.setIcon(QtGui.QIcon(animated_spinner.currentPixmap()))

Once you want to show the spinner, just start the QMovie:

animated_spinner.start()

If the spinner should disappear again, then stop the animation and 'hide' the spinner again. Once the animation is stopped, the frameChanged slot won't update the button anymore.

animated_spinner.stop()
pushButton.setIcon(QtGui.QIcon())