Search code examples
javaanimationiconsjframetitlebar

how use animated gif as JFrame title bar icon


Is it possible to use an animated .gif image as the icon of a JFrame?

example:

public class myFrame extends JFrame
{
    java.net.URL imgURL = getCLass().getResource("/icons/AnimatedGif.gif");
    ImageIcon icon = new ImageIcon(imgURL);

    this.setIconImage(icon.getImage());
    icon.setImageObserver(this);

    ...
}

This method has not worked for me. The application hangs prior to making the JFrame visible. Everything works fine though with a regular .gif icon.


Solution

  • I tried a while back to have the icon of my JFrame animated just by setting the icon image to an animated gif. I could never get that to work. I have come up with a work around though. No guarantees about correctness or thread safety.

    The basic idea is to have a separate thread that handles the icon animation. This thread's job is to constantly set the frame's icon image.

    This is a demo frame:

    import java.awt.EventQueue;
    import javax.swing.JFrame;
    
    public class FrameWithAnimatedIcon extends JFrame
    {
    public static void main(String[] args)
    {
        final FrameWithAnimatedIcon frame = new FrameWithAnimatedIcon();
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    frame.setVisible(true);
                } catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    
        IconAnimator animator = new IconAnimator(frame, Images.images, 250);
        animator.run();
    }
    
    public FrameWithAnimatedIcon()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
    
    }
    }
    

    This is the icon animator class:

    import java.awt.Image;
    import java.util.ArrayList;
    import javax.swing.JFrame;
    
    public class IconAnimator
    {
    
    JFrame           frame = null;
    ArrayList<Image> images;
    long             msBetweenImages;
    
    public IconAnimator(JFrame frame, ArrayList<Image> images, long msBetweenImages)
    {
        this.frame = frame;
        this.images = images;
        this.msBetweenImages = msBetweenImages;
    }
    
    public void run()
    {
        while(true)
        {
            for(Image image : images)
            {
                try
                {
                    frame.setIconImage(image);
    
                    Thread.sleep(msBetweenImages);
    
                } catch(InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                if(frame == null)
                {
                    return;
                }
            }
        }
    }
    }    
    

    With this IconAnimator class, I can give it the target frame, a list of images, and the time between images, and it will animate the JFrame icon. I imagine this code is probably not "best practices" material, however, it works. A side note on implementation, I made a separate class called Images that just loads my images into an ArrayList. Each image is 16x16. The list declaration of that class looks like this:

    public static ArrayList<Image> images = new ArrayList<Image>(){{
       add(Toolkit.getDefaultToolkit().getImage(
           Images.class.getResource("/toolbarButtonGraphics/development/Bean16.gif")));
    
       add(Toolkit.getDefaultToolkit().getImage(
               Images.class.getResource   ("/toolbarButtonGraphics/development/Application16.gif"))); 
    
       add(Toolkit.getDefaultToolkit().getImage(
               Images.class.getResource("/toolbarButtonGraphics/development/Applet16.gif"))); 
    
       add(Toolkit.getDefaultToolkit().getImage(
               Images.class.getResource("/toolbarButtonGraphics/development/WebComponent16.gif"))); 
    }};