PDA

View Full Version : How to place animated GIF on QGraphicsScene?



Gourmet
4th February 2015, 16:13
I have QGraphicsScene with QGraphicsItem-s. Now I need add animated images to some items. I created aniGIFs but don't see how to "attach" them to items. There is a way to show animated GIFs via QLabel with QMovie inside. But QLabel requires QWidget at least to define where to draw QLabel. I do not have any QWidget inside scene. QWidget and QGraphicsItem are independent drawing essences. They cannot mix. I tried inherit from both classes but got lots of errors even after MOC compiler.

How can I solve this? How animated GIF can be better placed on QGraphicsScene? Can this work if I create QWidget inside paint() event of my QGraphicsItem? Or there is any other lightweight way?

Gourmet
5th February 2015, 10:04
QMovie should be initialized with animated GIF, then QLabel::setMovie( QMovie ), QGraphicsProxyWidget must be initialized with parent QGraphicsItem then QGraphicsProxyWidget::setWidget( Qlabel). QGraphicsProxyWidget::setPos(X,Y) needed to set position of movie on QGraphicsItem. Finally call of QLabel::setAttribute(Qt::WA_NoSystemBackground) needed to allow transparent parts of GIF be transparent. All works.

anda_skoa
5th February 2015, 10:38
An alternative could be to use QMovie together with a QGraphicsPixmapItem and updating the item whenever the movie indicates a frame change.

Cheers,
_

Gourmet
5th February 2015, 14:36
But some problem persits.

I use QMovie on QLabel and QGraphicsProxyWidget to show animated GIF over QGraphicsItem placed on QGraphicsScene. Almost all works fine except one – at first start I see not entire GIF but only small left part of it. After I drag QGraphicsItem over scene (QDrag is used for it) – then QMovie fully appears. Exactly QDrag carries just pointer to QGraphicsItem object instead of serialized object.

All my actions I show here:


QLabel* aniLabel = new QLabel();
QMovie* aniMovie = new QMovie( ":/new/prefix1/anim-1-color.gif", QByteArray(), this );
QGraphicsProxyWidget* aniWidget = new QGraphicsProxyWidget( this );
aniLabel->setAttribute( Qt::WA_NoSystemBackground );
aniLabel->setMovie( aniMovie );
aniWidget->setWidget( aniLabel );

these actions I perform in constructor of item class derived from QGraphicsItem. To setup position of QGraphicsProxyWidget on QGraphicsItem and show animation I use following code:


aniWidget->setPos( pic.width() - aniLabel->size().width(),
pic.height() - aniLabel->size().height() );
aniLabel->show();
aniMovie->start();

it is placed in paint(…) event of item class derived from QGraphicsItem.

My question is – are there some necessary actions to be done with QMovie before show it with QLavel? Or may be this is a problem with QLabel itself?

Added after 12 minutes:

I SOLVED!! There is a bug in QMovie implementation. After first setting animated GIF it accepts size of only first frame. To properly initialize image properties from all frames QMovie must be started and stopped right now.

I did


aniMovie->start();
aniMovie->stop();

right before


aniLabel->setMovie( aniMovie );

and animation now appears from first start.

Can anybody tell me - how QMovie works in Qt 5.x? Is start/stop needed to display animated GIF properly?