Gif Animation in Qt

GIF animation in Qt

I don't use GIF animation with QGraphicsView or QGraphicsScene, I use it only in QDialog, but I think it's the same stuff, so here is my code:

QMovie *movie = new QMovie(":/images/other/images/16x16/loading.gif");
QLabel *processLabel = new QLabel(this);
processLabel->setMovie(movie);
movie->start();

My loading.gif I took from this link.


PS: also check the examples from Qt SDK. They are really can help!

Showing a .gif animation in QLabel

you can add a Layout to the label, and then add another Label with the text to that...

self.status_txt = QtGui.QLabel()
movie = QtGui.QMovie("etc/loading.gif")
self.status_txt.setMovie(movie)
movie.start()
self.status_txt.setLayout(QtGui.QHBoxLayout())
self.status_txt.layout().addWidget(QLabel('Loading...'))

edit:

it's possible if you use your own version of a QLabel and a QPainter to paint the text yourself:

from PyQt4.QtCore import QSize
from PyQt4.QtGui import QApplication, QLabel, QMovie, QPainter, QFontMetrics

class QTextMovieLabel(QLabel):
def __init__(self, text, fileName):
QLabel.__init__(self)
self._text = text
m = QMovie(fileName)
m.start()
self.setMovie(m)

def setMovie(self, movie):
QLabel.setMovie(self, movie)
s=movie.currentImage().size()
self._movieWidth = s.width()
self._movieHeight = s.height()

def paintEvent(self, evt):
QLabel.paintEvent(self, evt)
p = QPainter(self)
p.setFont(self.font())
x = self._movieWidth + 6
y = (self.height() + p.fontMetrics().xHeight()) / 2
p.drawText(x, y, self._text)
p.end()

def sizeHint(self):
fm = QFontMetrics(self.font())
return QSize(self._movieWidth + 6 + fm.width(self._text),
self._movieHeight)

def setText(self, text):
self._text = text

if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
l = QTextMovieLabel('Loading...', 'loading.gif')
l.show()
app.exec_()

Switch between GIF animations with QMovie and signals/slots in Qt

First, for removing the error, just declare your QMovie in your header file (which I believe is the one named abv.h).

In your .h :

private : 
QMovie* _movie;

In your .cpp :

abv::abv(QWidget *parent) :
QDialog(parent, Qt::FramelessWindowHint),
ui(new Ui::abv)
{
QString project = projectGifs();
_movie = new QMovie(project); // this line changes
...

Now, you connect the signal frameChanged(int) to the constructor abv::abv(). It won't work because :

  • mainly, your constructor can't be a slot ;
  • the signature is not the same (the slot must take an int as a parameter, like the signal does)

Moreover, why are you doing it like this? The signal frameChanged(int) is emitted each time a new image is sent to the user(!). You are currently telling your program to launch a new GIF everytime a frame changes. Your code won't work this way.

If I understand well, you just have to connect the signal QMovie::finished() to a slot where you will call another GIF. Your QLabel will have to be a class variable as well. Something like this :

In your .h :

private
QMovie* _movie;
QLabel* _label;

public slots :
void startNewAnimation();

And in your .cpp :

abv::abv(QWidget *parent) :
QDialog(parent, Qt::FramelessWindowHint),
ui(new Ui::abv)
{
QString project = projectGifs(); //projectGifs() is a function stated in my header that sends over a randomly selected gif
_movie = new QMovie(project);
if (!_movie->isValid())
cout << "The gif is not valid!!!";
_label = new QLabel(this);
QObject::connect(
_movie, SIGNAL(finished()),
this, SLOT(startNewAnimation())); //stop animation and get new animation
_label->setMovie(_movie);
_movie->start();
}

void abv::startNewAnimation()
{
// here you need to call your new GIF
// and then you just put it in your label

// you can also disconnect the signal finished() if you want

QString newGIF = projectGifs();
_movie = new QMovie(newGIF);
_label->setMovie(_movie);
}

Animated GIF ins't displayed with Qt on Windows

First, sorry for my bad english. I managed to solve this in 3 steps. I don't know whether it is correct way to do it but it works!

  1. Create a folder name 'imageformats' in the same directory of your application.
  2. Copy qgif.dll from your qt plugins directory and paste to the folder.
  3. Put your gif files in the same folder.

Note:
But make sure to set your current path of QMovie's object correctly.
For e.g :
eye_right = new QMovie(QDir::currentPath()+"/imageformats/eye_right.gif");

gif image in QLabel

The problem is that QLabel has window background by default. You're trying to remove it by do it incorrectly:

FramelessWindowHint doesn't make sense here, since it's only used for top level widgets, and a widget added to scene is technically hidden and doesn't have system window frame. This line should be removed.

setMask does exactly what you describe it does. Since QPixmap is not animated, its mask is the alpha mask of the first frame of animation. And you permanently apply this mask to the label. It's not surpising that it works, but obviously it's not what you want. This line should also be removed.

setGeometry line is incorrect. It prevents picture from being visible for me. Label has good size by default and there is no need for setGeometry. If you want to scale or move the item on the scene, you can do it after addWidget as for any other QGraphicsItem. E.g. addWidget(lbl)->setPos(10, 10).

The magic bullet you need is WA_NoSystemBackground. It disables background painting for QLabel completely. So, the full code would be:

QLabel *lbl = new QLabel;
QMovie *mv = new QMovie("c:/tmp/sun.gif");
mv->start();
lbl->setAttribute(Qt::WA_NoSystemBackground);
lbl->setMovie(mv);
scene.addWidget(lbl);

It works fine for me. However I consider it over-complicated. You should not use proxy widgets in scene unless necessary. You can easily add a movie using QMovie and QGraphicsPixmapItem and switching pixmaps as movie frames change. I wrote a convenient class for this:

Header:

class GraphicsMovieItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
GraphicsMovieItem(QGraphicsItem* parent = 0);
void setMovie(QMovie* movie);

private:
QMovie* m_movie;

private slots:
void frameChanged();
};

Source:

GraphicsMovieItem::GraphicsMovieItem(QGraphicsItem *parent)
: QGraphicsPixmapItem(parent), m_movie(0) {
}

void GraphicsMovieItem::setMovie(QMovie *movie) {
if (m_movie) {
disconnect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
}
m_movie = movie;
if (m_movie) {
connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
}
frameChanged();
}

void GraphicsMovieItem::frameChanged() {
if (!m_movie) { return; }
setPixmap(m_movie->currentPixmap());
}

Usage:

QMovie *mv = new QMovie("c:/tmp/sun.gif");
GraphicsMovieItem* item = new GraphicsMovieItem();
item->setMovie(mv);
scene.addItem(item);


Related Topics



Leave a reply



Submit