I'm trying to display a GIF file to a JLabel. No problem I load the GIF and set it as the icon of the label. But now i really need to know when this ends, because it has to function as a cutscene. What i already tried is this (GameScene is a custom object but i know setIcon works, trust me) :
private GameScene scene;
private ImageIcon _temp;
private ImageIcon toplay;
private Thread anim;
public Cutscene(ImageIcon gif, GameScene scene, int length){
this._temp = scene.getIcon();
this.toplay = gif;
this.scene = scene;
anim = new Thread(){
@Override
public void run(){
scene.setIcon(gif);
scene.repaint();
try {
Thread.sleep(length);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
private void _s(){
scene.setSolidColor(false);
scene.setIcon(toplay);
scene.repaint();
}
public void play(){
_s();
anim.start();
}
public void await(){
try {
anim.join();
scene.setIcon(_temp);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now, Is there anyway I can achieve this without, just letting the whole program sleep for the given amount of time and then continue with the rest of the code and completely not drawing the GIF file?
This is a really simply example, it will only work with non-looping gifs, if your gif repeats you'll have to test the time between requests for FRAMEBITS
and try and determine if you can detect the point at which loops.
public class MonitoringLabel extends JLabel {
public MonitoringLabel(Icon image) {
super(image);
}
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
protected void fireActionPerformed() {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
if (listeners.length > 0) {
ActionEvent evt = new ActionEvent(this, 0, "stopped");
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
boolean finished = super.imageUpdate(img, infoflags, x, y, w, h);
if (!finished) {
fireActionPerformed();
}
return finished;
}
}
The above class provides an ActionListener
which is triggered when the image "finishes" loading (this is triggered when their are no new frames in the animation to be played - repeating gifs never return false
)
You can use a different listener interface if you want, I just threw it together as an example.
The reason I choose to override imageUpdate
is because the JLabel
is already acting as the ImageObserver
to the image when it paints it, this way we can use the power of the JLabel
without fussing about with manually painting a gif ... yes I've done it, it's pain
Would it be possible to make the GIF non-repeating with the program used to make it? Most photo editors that make GIF images give you the option of making it repeating or not.
If I'm understanding your problem, it seems like you just want the gif to play once?
If it's for a cut scene, why not make the program sleep during that time?