0

I got my code to draw my image in an applet, but it is an animated gif and it is stopped on the first frame as if it were a single image.

It is supposed to be the spooky scary skeleton dancing, but he's just standing still.

Here is my code:

import java.util.*;
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.*;

public class Spooky extends Applet
{
Image scary, trumpet, walking;
MediaTracker mt;
AudioClip spoopy;
Graphics buffer;
Image offscreen;
Dimension dim;

public void init()
{
setLayout(null);
mt = new MediaTracker(this);


mt.addImage(scary,1);
mt.addImage(trumpet,1);
mt.addImage(walking,1);
spoopy = getAudioClip(getDocumentBase(),"spoopy.wav");
spoopy.loop();
}

public void paint(Graphics g)
{
  try
{
    URL url = this.getClass().getResource("spooky.gif");
    BufferedImage img;
    img = ImageIO.read(url);
    mt.addImage(img,1);
    g.drawImage(img,0,0,300,300,this);
}
catch(IOException e)
{
}

}
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Ryan Dwyer
  • 49
  • 2
  • 7
  • 1) Why code an applet? If it is due to the teacher specifying it, please refer them to [Why CS teachers should **stop** teaching Java applets](http://programmers.blogoverflow.com/2013/05/why-cs-teachers-should-stop-teaching-java-applets/). 2) Why use AWT? See [this answer](http://stackoverflow.com/questions/6255106/java-gui-listeners-without-awt/6255978#6255978) for many good reasons to abandon AWT using components in favor of Swing. 3) See also [Show an animated BG in Swing](http://stackoverflow.com/q/10836832/418556). – Andrew Thompson Oct 21 '14 at 21:33

3 Answers3

2

The problem is the ImageIO.read(url); method. Not sure how, but internally, it messes up the reading of the gif. Instead, construct an ImageIcon from the URL and use getImage() of the ImageIcon to get an Image

As an aside, don't load the image in the paint method. Load it in the init method.

public class Spooky extends Applet {
    Image image;

    public void init() {
        URL url = this.getClass().getResource("spooky.gif");
        image = new ImageIcon(url).getImage();
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(image, 0, 0, 300, 300, this);
    }  
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I'm getting the error "Incompatible Types" with your method. Could it be because I'm using a BufferedImage rather than an Image? – Ryan Dwyer Oct 21 '14 at 16:28
  • Yes, `getImage()` doesn't return a `BufferedImage` – Paul Samsotha Oct 21 '14 at 16:29
  • Do you know how I could get this to work with a BufferedImage? I dislike the flickering of a regular image. – Ryan Dwyer Oct 21 '14 at 16:36
  • @RyanDwyer From https://www.java.net/node/683927 "You can try, but it will only draw the "current" frame of the GIF to the BufferedImage. BufferedImage objects are just static buckets of pixels so they can't "animate"." – Michail Michailidis Oct 21 '14 at 16:46
  • 1
    Welp I guess I'm using a regular image. Thanks for your help! – Ryan Dwyer Oct 21 '14 at 16:47
  • @peeskillet That's what I posted about an hour earlier than you - also JApplet is the suggested solution since awt.Applet is so old. – Michail Michailidis Oct 21 '14 at 16:49
  • @MichailMichailidis Yes I know that, but the OP is using Applet. For all I know this is a class assignment, where the teacher is teaching Applets. I have no control over that. Personally, I would never use Applet though. – Paul Samsotha Oct 21 '14 at 16:52
  • class assignment? wait what? - apart from that you reposted the same thing and you got all the credit :P Never mind – Michail Michailidis Oct 21 '14 at 16:52
  • @MichailMichailidis And My answer is _not_ any way like yours. You are using a JLabel and ImageIcon, while my answer is still using custom painting – Paul Samsotha Oct 21 '14 at 16:53
  • @MichailMichailidis suggested by whom? Who says you shouldn't try and paint a gif. I'd like to see some backing for that statement. Maybe with evidence, I will stop giving this approach. I mean if it works, it works. – Paul Samsotha Oct 21 '14 at 16:54
  • Most of the books and a lot of other stackoverflow examples put the imageIcons in JLabels http://alvinalexander.com/blog/post/jfc-swing/use-animated-gif-image-in-jfc-swing-application http://stackoverflow.com/questions/11382827/imageicon-in-java Oreilly Examples: http://examples.oreilly.com/jswing2/code/ - A lot of things "work" but are bad practices or give you less control like drawing directly in JApplet and JFrame - instead of calling getContentPane etc.. – Michail Michailidis Oct 21 '14 at 16:58
  • @MichailMichailidis those are just example, but they don't explicitly say _not_ to paint with an `Image`. I've seen all those posts. But in the context of this particular posted question, without more context on requirements, I answered it in the context of what the OP was trying to do. And that was painting. Whether or not I would use an ImageIcon/JLabel or a paint the Image, it's a matter of what exactly is required. So I won't say that you _shouldn't_ paint the gif, because I have use for it sometimess – Paul Samsotha Oct 21 '14 at 17:01
  • You are avoiding to admit that you posted a question of ImageIcon (which is the solution to the problem since BufferedImage doesn't work with gifs - two hours later than mine and getting the credit). Also all this this.getClass().getResource("spooky.gif") is not even needed – Michail Michailidis Oct 21 '14 at 17:03
  • OK drawing on the top level container I give you that. But that is not the issue at hand here. Until I receive some confirmation that its bad practice to paint the gif, I can't go off of a statement like, "but everyone else does it this way" – Paul Samsotha Oct 21 '14 at 17:04
  • @MichailMichailidis is that what you want, credit. I don't care about the credit. You can have it. But please don't make arguments for which you don't have backing. +1 for your answer though. – Paul Samsotha Oct 21 '14 at 17:05
  • Thanks - this is what it is about plus right code guidelines that 90%+ people use for better control/quality. +1 from me – Michail Michailidis Oct 21 '14 at 17:07
1

I don't know if it helps but usually it is a problem of needing a separate Thread/Runnable for the animation and a separate for the rest of the code. At least that was a problem I had when I was making a small game. Try this one and let me know if it helps :)

Check this too: Displaying Gif animation in java

Update: An example I found (http://examples.oreilly.com/jswing2/code/) uses JApplet that supports gifs (Applet is the old one)

// AnimationApplet.java
// The classic animation applet rewritten to use an animated GIF.
//
import javax.swing.*;

public class AnimationApplet extends JApplet {
  public void init() {
    ImageIcon icon = new ImageIcon("images/rolling.gif");  // animated gif
    getContentPane().add(new JLabel(icon));
  }
}

Did you try not to put sound to see if animation works alone? It could be that sound needs a separate Runnable/Thread

Community
  • 1
  • 1
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106
0

I had a similar problem. Michail Michailidis's answer is one solution. However, if you are trying to load the GIF from an InputStream (which was the situation in my case) you will need a different solution. In this case, I would use the Toolkit class to load your image, more specifically, Toolkit#createImage(byte[]):

Image image;
try(InputStream stream = this.getClass().getResourceAsStream("/someImage.gif")) {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int nRead;
    byte[] data = new byte[16384];

    while ((nRead = stream.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, nRead);
    }

    buffer.flush();

    image = Toolkit.getDefaultToolkit().createImage(buffer.toByteArray());
} catch (IOException e) {
    e.printStackTrace();
}
Cardinal System
  • 2,749
  • 3
  • 21
  • 42