PDA

View Full Version : QMovie displays only last frame



dbrayford
2nd July 2012, 16:23
I am trying to create an animation from an animated gif, where I jump to a particular frame based on an input from within a loop (see below). However, only the last frame is being displayed and think I need to flush the buffer, but don't know how Or maybe there is some other method to show the individual frames inside the loop.



for(int i = 0; i < vec.size(); i++)
{
movie.jumpToFrame( vec.at(i) );
}

high_flyer
2nd July 2012, 16:25
Check the size of the vector at runtime.
It might actually be holding only one frame.

d_stranz
2nd July 2012, 16:47
No, I think the problem is that inside this for loop, the Qt event loop isn't being allowed to run. So what is happening is that all of the frames *are* being jumped to, but because paint events are just stacking up without being handled, all of them are getting removed except for the last one that paints the final frame.

You could add a call to QApplication:: processEvents() inside the loop, but this probably would not give satisfactory results either, since the frames would be displayed as fast as Qt could handle them. So visually all the viewer would be able to see is the last frame because the others flash by too quickly to be "seen" by the user's visual system.

The best solution is probably to use the Qt animation framework to step through the frames, or to implement a QTimer and a timeout() handler that will do it for you:



void MyWidget::showMovie()
{
currentFrame = 0; // member variable
timer.setInterval( 33 ); // "timer" is also a member variable; 33 ms is roughly 30 frames / sec rate
connect( &timer, SIGNAL( timeout() ), this, SLOT( showFrame() ) );
showFrame();
timer.start();
}

void MyWidget::showFrame()
{
if ( currentFrame >= 0 && currentFrame < vec.size() )
{
movie.jumpToFrame( vec.at( currentFrame ) );
currentFrame++;
}
else
{
timer.stop();
}
}

Note that this code displays the movie only once. If you want to loop repeatedly through the animation, replace the timer.stop(); call with currentFrame = 0; movie.jumpToFrame( vec.at( currentFrame ) );

high_flyer
2nd July 2012, 16:57
am trying to create an animation from an animated gif, where I jump to a particular frame based on an input from within a loop (see below).
Why are you using a loop at all if what you want is to jump to a particular frame?

@d_stranz
To show the movie you can just do: movie.start();

d_stranz
2nd July 2012, 17:03
To show the movie you can just do: movie.start();

From the context of the OP, I assumed that images from the animated GIF were not contained in a QMovie, but in some other data structure which had to be accessed manually. If it is in fact a QMovie, then movie.start() would obviously be the right choice.

It's Monday morning here, not fully awake yet.

high_flyer
2nd July 2012, 17:06
From the context of the OP, I assumed that images from the animated GIF were not contained in a QMovie, but in some other data structure which had to be accessed manually.
But then it wouldn't make much sense to jumpToFrame() in the movie, if it is not containing the frames... ;)
Indeed the OP's choice to loop through the movie while wanting to jump to a specific frame eludes me.

dbrayford
2nd July 2012, 17:16
I am using the loop and jumpToFrame() because the the frame I want to jump to isn't in sequential order (2, 5, 1, 10, 30, 6 ...).

high_flyer
2nd July 2012, 17:38
I am using the loop and jumpToFrame() because the the frame I want to jump to isn't in sequential order (2, 5, 1, 10, 30, 6 ...).
Still, you are jumping to many frames in the loop, not to *a* frame, and you see the last one you jumped to.
First loop over your vector, find your desired frame index, and then, outside the loop do the jump to that index.

d_stranz
2nd July 2012, 17:38
I am using the loop and jumpToFrame() because the the frame I want to jump to isn't in sequential order (2, 5, 1, 10, 30, 6 ...).

Well, then the QTimer method I suggested would let you do that. Whatever you choose to do, you have to let Qt's event loop process the paint event generated by the jumpToFrame() call, otherwise you'll only see a frame change when Qt is finally allowed to process events. The QTimer method does that automatically for you since the whole thing is handled within the event loop concept.