Simple animations can be achieved by using a JLabel, series of images and setIcon(). You can create a panel with a overridden paint() (or paintComponent()) - and call repaint from a Timer, but then you have to get much more involved in the Swing Painting Model. Theoretically, this would also skip wrapping images into ImageIcons and then extracting images to paint them, and also save some memory and gain performance. But, if you need advanced animations with exact timing or performance, use Java Media Framework. If you need just a simple1) animation, use this wrapper. JMF also requires you to package the JMF libraries with your application, that may be a bit too much if you are just writing an applet.
Objects of this class are for one-time usage2). To prevent memory leaks, they release all image resources when being removed from the screen or panel (in removeNotify). They also automatically take care about starting and stopping animations when added and removed from the screen.
import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import javax.swing.*; import javax.swing.JLabel; /** * A label that takes care of background animations, and automatically * stops animating after being removed from the screen. * * @version 0.2, 23.12.2004 * -0.2 cleaned the thread model */ public class AnimatedLabel extends JLabel { public ImageIcon[] icons; private volatile boolean animationsRunning=false; int delay; int pauseBetween; private int currentIndex=0; private boolean runOnce; private boolean disposed=false; public AnimatedLabel( String imageResourcePrefix, String imageResourceSuffix, int startIndex, int delay, int pauseBetweenAnimations, boolean runOnce){ ArrayList iconsList=new ArrayList(); boolean hasMore=true; for (int i=0; hasMore; i++){ try{ String file=imageResourcePrefix+(i+startIndex)+imageResourceSuffix; // ImageHelper is a utility class that loads images //using the current classloader iconsList.add(ImageHelper.getImageIcon(file)); } catch (IllegalArgumentException nex){ hasMore=false; } } icons=new ImageIcon[iconsList.size()]; int index=0; for (Iterator i=iconsList.iterator();i.hasNext();index++){ icons[index]=(ImageIcon) i.next(); } setIcon(icons[0]); this.delay=delay; this.pauseBetween=pauseBetweenAnimations; this.runOnce=runOnce; } public AnimatedLabel( String imageResourcePrefix, String imageResourceSuffix, int numImages, int startIndex, int delay, int pauseBetweenAnimations, boolean runOnce){ icons=new ImageIcon[numImages]; for (int i=0; i<numImages; i++){ // ImageHelper is a utility class that loads images //using the current classloader icons[i]=ImageHelper.getImageIcon( imageResourcePrefix+(i+startIndex)+imageResourceSuffix); } setIcon(icons[0]); this.delay=delay; this.pauseBetween=pauseBetweenAnimations; this.runOnce=runOnce; } public AnimatedLabel(String imageResourcePrefix, String imageResourceSuffix, int numImages, int startIndex, int delay, int pauseBetweenAnimations){ this(imageResourcePrefix, imageResourceSuffix, numImages, startIndex, delay, pauseBetweenAnimations, false); } /** * @see javax.swing.JComponent#addNotify() * */ public void addNotify() { if (disposed) throw new IllegalStateException ("Already disposed"); super.addNotify(); runAnimations(); } public void removeNotify() { super.removeNotify(); stopAnimations(); disposeResources(); } private void disposeResources(){ disposed=true; Arrays.fill(icons,null); } private Thread animatorThread; public void runAnimations(){ if (!animationsRunning){ animationsRunning=true; animatorThread=new Animator(); animatorThread.start(); } } public void stopAnimations(){ animationsRunning=false; animatorThread.interrupt(); animatorThread=null; } public void joinThread() throws InterruptedException{ animatorThread.join(); } private class Animator extends Thread{ public void run() { try{ while (animationsRunning){ sleep(delay); currentIndex= (currentIndex+1)%icons.length; SwingUtilities.invokeAndWait(new Runnable(){ public void run(){ setIcon(icons[currentIndex]); } }); if (currentIndex==icons.length-1 && runOnce) animationsRunning=false; if (currentIndex==0) sleep(pauseBetween); } } catch (InterruptedException ex){ } catch (InvocationTargetException ex){ ex.printStackTrace(); } } } }