Question

QPushButton can have icon, but I need to set animated icon to it. How to do this? I created new class implemented from QPushButton but how to replace icon from QIcon to QMovie?

Was it helpful?

Solution 2

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())

OTHER TIPS

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();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top