Animated GIF Viewer

R

Rhino

I need a bit of help from someone who has worked with animated GIFs in Java.

I am trying to build a simple animated GIF viewer that contains a panel for
displaying an animated GIF and two buttons, Start and Stop. The name of the
single file containing the animated GIF should be passed to the constructor.
Then, when the Start button is clicked by the user, the animated GIF should
start playing. When the user clicks the Stop button, the animation should
freeze at the frame that is playing when the button is clicked.

Basically, I think the problem is that my paintComponent() method is not
doing the wrong thing in the 'if (!keepDrawing)' branch. I've tried umpteen
things in there and none of them is fully satisfactory. The best I've been
able to do is in the current version of the code where the animation freezes
when the Stop button is clicked. Unfortunately, other junk from the GUI gets
displayed over top of the frozen picture: the Start or Stop button gets
drawn over top of the frozen picture, depending on where the mouse is??!!

I've supplied the simplest version of the code that I can below; I've
removed everything except the essential code and a few important comments.
If anyone can tell me what I need to do to freeze the animation when the
Stop button is clicked WITHOUT having other junk written over the frozen
picture, I'd be grateful to hear from you!

All you need to do to make this code work for you is:
- find an animated GIF to use. If you don't have one handy, there are many
such sites offering free downloadable animated GIFs accessible via Google,
such as http://www.gifanimations.com/. Just download one of theirs for the
purpose of trying this code.
- modify the line in the TempAnimationPanel constructor that starts 'URL
animationGIF = " to point to your animated GIF, either in a jar or on your
file system.

--File:
TempAnimationDisplayer.java-------------------------------------------------
-----------------------
package ca.tonge.common;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TempAnimationDisplayer extends JPanel implements ActionListener
{

TempAnimationPanel drawingPanel = null;

public static void main(String[] args) {

/*
* Create a frame that will display the animated image. Ensure that
* clicking on the JFrame's Close button ("X" in top right corner)
kills
* the application.
*/
JFrame myFrame = new JFrame("Animated GIF Viewer");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

TempAnimationDisplayer tempAnimationDisplayer = new
TempAnimationDisplayer();
myFrame.getContentPane().add(tempAnimationDisplayer);
myFrame.pack();
myFrame.setVisible(true);
}

public TempAnimationDisplayer() {

setLayout(new BorderLayout());

/* Construct the panel that shows the animated GIF and add it to the
main panel. */;
drawingPanel = new TempAnimationPanel("AnimatedGIFs/dog.gif",
false);
add(drawingPanel, BorderLayout.CENTER);

/* Construct the control button panel and add it to the main panel.
*/
JPanel buttonPanel = new JPanel();
JButton startButton = new JButton("Start");
startButton.addActionListener(this);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(this);
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
add(buttonPanel, BorderLayout.SOUTH);

}


public void actionPerformed(ActionEvent actionEvent) {

String command = actionEvent.getActionCommand();

if (command.equals("Start")) {
drawingPanel.startAnimation();
}
else
if (command.equals("Stop")) {
drawingPanel.stopAnimation();
}
else {
System.out.println("Ignoring unexpected command, " + command +
".");
}
}
}

--File:
TempAnimationPanel.java-----------------------------------------------------
------------------------
package ca.tonge.common;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.net.URL;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TempAnimationPanel extends JPanel implements Runnable {

final String CLASS_NAME = getClass().getName();
static final boolean DEBUG = false;
Thread animationThread = null;
boolean keepDrawing;
boolean frozen = false;
Image animation = null;
MediaTracker tracker = null;
int stillWidth = 0;
int stillHeight = 0;
private String animationImageFile = null;

public static void main(String[] args) {

/* Create a frame that will display the animated image. Ensure that clicking
on the
JFrame's Close button ("X" in top right corner) kills the application. */
JFrame myFrame = new JFrame("Animation Panel");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

/* Create the Animation panel and put it in the frame. */
TempAnimationPanel drawingPanel = new
TempAnimationPanel("AnimatedGIFs/catwalk.gif", true);
myFrame.getContentPane().add(drawingPanel, BorderLayout.CENTER);
myFrame.pack();
myFrame.setVisible(true);
}

public TempAnimationPanel(String animationImageFile, boolean
controlWithMouse) {

super();

String METHOD_NAME = "AnimationPanel()";

this.animationImageFile = animationImageFile;

/* Get the URL for the animated image file. */
URL animationGIF =
this.getClass().getClassLoader().getResource(animationImageFile);
if (animationGIF == null) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Couldn't play
animated GIF, " + animationGIF + ".");
System.exit(16);
}

/* Get the actual image file. */
animation = Toolkit.getDefaultToolkit().getImage(animationGIF);

try {
tracker = new MediaTracker(this);
tracker.addImage(animation, 0);
tracker.waitForAll();
}
catch (Exception excp) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Error
encountered while loading the image file for the Animation panel. Details:
");
excp.printStackTrace();
}

/* Assuming that all of the stills in the animation are the same size,
determine the
height and width of the panel that will be needed to display them. */
stillWidth = animation.getWidth(this);
stillHeight = animation.getHeight(this);

} //end TempAnimationPanel()


public String getAnimationFile() {

return animationImageFile;
}

/**
* Method startAnimation() starts the animation if the file being displayed
is an
* animated GIF. If the file is an ordinary (non-animated) GIF, this method
causes
* it to be displayed.
*/
public void startAnimation() {

String METHOD_NAME = "startAnimation()";

if (animationThread == null) {
if (DEBUG) System.out.println(CLASS_NAME + "." + METHOD_NAME + " -
Instantiating thread...");
animationThread = new Thread(this);
keepDrawing = true;
animationThread.start();
}
} //end startAnim()

/**
* Method stopAnimation() sets the flag, keepDrawing, that will tell the
paintComponent()
* method not to draw the animation. This effectively pauses the animation
until the user
* chooses to restart it. If the picture is an ordinary (non-animated) GIF,
the flag is
* set just the same but the still remains unchanged so there is no visible
effect.
*/
public void stopAnimation() {

if (animationThread != null) {
keepDrawing = false;
animationThread = null;
}
} //end stopAnim()


/**
* Method run() simply repaints and pauses briefly if the flag says that the
thread
* is still active; otherwise, nothing at all happens.
*/
public void run() {

String METHOD_NAME = "run()";

while (keepDrawing) {
repaint(); //call paint
try {
Thread.sleep(10); //sleep a little to slow it down
}
catch (InterruptedException ie_excp) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Error: +
ie_excp.");
}
} //end while
} // end run()


/**
* Method paintComponent() draws the animation or still if the flag is true;
otherwise,
* the previous state of the picture is left alone.
*/
public void paintComponent(Graphics graphics) {

/* If the toggle indicates that no drawing should take place, return without
drawing
anything. Otherwise, run the animation. */
if (!keepDrawing) {
//what goes here so that I freeze on the current frame of the
animation?
}
else {
super.paintComponent(graphics);
graphics.drawImage(animation, 0, 0, this);
}

} //end paint()


public Dimension getPreferredSize() {

return new Dimension(stillWidth, stillHeight);
}
} //end of class


--
Rhino
---
rhino1 AT sympatico DOT ca
"There are two ways of constructing a software design. One way is to make it
so simple that there are obviously no deficiencies. And the other way is to
make it so complicated that there are no obvious deficiencies." - C.A.R.
Hoare
 
L

Loek Raemakers

Hallo,

Using an animated gif means setting the number of times the stills are shown.
Suppose I chose for an infinite loop how will an image be drawn with your code:

if (!keepDrawing)
{
//what goes here so that I freeze on the current frame of the animation?
}
else
{
super.paintComponent(graphics);
graphics.drawImage(animation, 0, 0, this);
}

Only when I leave out the if - else, the image is shown on my computer.

Besides, the image is only drawn when I also leave out the getClassLoader() in
the URL:
this.getClass().getClassLoader().getResource(animationImageFile);

I hope you manage your problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top