Java/2D Graphics GUI/Animation — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
 
м (1 версия)
 
(нет различий)

Текущая версия на 06:55, 1 июня 2010

Animated Button

   
/**
 *   Arsenal Real-Time Collaboration Server Project
 *   Copyright (C) 2003  Michael Burnside, Arsenal Project
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***************************************************************** 
 *    $Header: /cvs/coolcollaborator/prod/coolcollaborator/prod/util/src/com/arsenal/util/AnimatedButton.java,v 1.1.1.1 2006/01/12 04:54:02 mburnside Exp $ 
 *     
 *    File: $Workfile: AnimatedButton.java $ 
 *     
 *    Description: 
 *     
 *    
 *     
 *    @author      michael@michaelburnside.ru (arsenal-1) 
 *    @author      Michael Burnside 
 *    @version     %I%, %G% 
 *    @since       1.0 
 *     
 */
import java.io.File;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AnimatedButton extends JPanel {
        
        Font font = new Font("Arial", Font.PLAIN, 10);
        Color darkSlateGray = new Color(49,79,79);
        Color dimGray = new Color(105,105,105);
        Color slateGray = new Color(112,138,144);
        Color lightSlateGray = new Color(119,136,153);
        Color gray = new Color(190,190,190);
        Color lightGray = new Color(211,211,211);
        Color[] colors = { Color.black, darkSlateGray, dimGray, slateGray,
                lightSlateGray, gray, lightGray, Color.white };
        
  private JButton button = new JButton();
        private int fadeSpeed = 50;
        private boolean animate = false;
        private boolean allowAnimate = true; // we will animate
  private Color foreground = Color.black;
  public void setDefaultForeground(Color foreground) { this.foreground = foreground; }
  
  public AnimatedButton(String buttonText, boolean useBgImage, Color defaultForeground, boolean allowAnimate) { 
    this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
          button.setText(buttonText);
    this.foreground = defaultForeground;
          this.allowAnimate = allowAnimate;
          setOpaque(false);
          add(button);
          if(allowAnimate)
            runThread.start();
  }
        
        
        private Thread runThread = new Thread(
          new  Runnable() {    
            public void run() {
              while(true) {
               try { runThread.sleep(100); } catch(Exception e) { }       
               if(animate) {
                 for(int i = 0; i < colors.length; i++) {
                   button.setForeground(colors[i]);
                   try { runThread.sleep(fadeSpeed); } catch(Exception e) { }
                 }
                 try { runThread.sleep(100); } catch(Exception e) { }
                 for(int i = colors.length -1 ; i >= 0; i--) {
                   button.setForeground(colors[i]);      
                  try { runThread.sleep(fadeSpeed); } catch(Exception le) { }
                 }
               } // end if animate
              } //end while
            }
          }
        );
        /**
         *
         * Sets the button"s and panel"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setMaximumSize(int width, int height) {
           setMaximumSize(new Dimension(width, height));
           button.setMaximumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the button"s and panel"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setMinimumSize(int width, int height) {
           setMinimumSize(new Dimension(width, height));
           button.setMinimumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the button"s and panel"s preferred size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setPreferredSize(int width, int height) {
           setPreferredSize(new Dimension(width, height));     
           button.setPreferredSize(new Dimension(width, height));       
        }
        /**
         *
         * gets the button instance
         *
         * @return JButton component of this class
         *
         */        
        public JButton getButton() {
           return button;       
        }
        
        public void setText(String text) {
           button.setText(text);
        }
        
        public void setEnable(boolean animate) {
                if(allowAnimate) {
                  this.animate = animate;
                  if(!animate)
                    button.setForeground(Color.black);
                  button.setEnabled(animate);
                }
                else {
                  button.setEnabled(animate);
                }
        }
        
}



Animated Message Panel

   
/**
 *   Arsenal Real-Time Collaboration Server Project
 *   Copyright (C) 2003  Michael Burnside, Arsenal Project
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***************************************************************** 
 *    $Header: /cvs/coolcollaborator/prod/coolcollaborator/prod/util/src/com/arsenal/util/AnimatedMessagePanel.java,v 1.1.1.1 2006/01/12 04:54:02 mburnside Exp $ 
 *     
 *    File: $Workfile: AnimatedMessagePanel.java $ 
 *     
 *    Description: 
 *     
 *    A special panel that can scroll text messages and resize itself
 *     
 *    @author      michael@michaelburnside.ru (arsenal-1) 
 *    @author      Michael Burnside 
 *    @version     %I%, %G% 
 *    @since       1.0 
 *     
 */

import javax.swing.*;
import javax.swing.border.*;
import javax.accessibility.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Hashtable;
import java.util.TreeMap;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.Enumeration;
import java.awt.font.*;
import java.awt.geom.*;
public class AnimatedMessagePanel extends JPanel implements Runnable {
  private Graphics og = null;
  private Image offscreen = null;
  private int height = 230;
  private int width = 575;
  private int x = 0;
  private int y = 0;
  private Thread animator = null;
  private Graphics g = null;
  //private Graphics2D g2 = null;
  private boolean started = false; 
  private String[] messageQue = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; // size is 5
  private Font font = new Font("Arial", Font.PLAIN, 11);
  private boolean currentlyScrolling = false;
  private void setCurrentlyScrolling(boolean currentlyScrolling) { this.currentlyScrolling = currentlyScrolling; }
  private boolean isCurrentlyScrolling() { return currentlyScrolling; }
  private String[] messageWaitingQue = { "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; // also size 5, its for if a message arrives while we are currently scrolling
    
  private static AnimatedMessagePanel instance = new AnimatedMessagePanel();
  public static AnimatedMessagePanel getInstance() {
    if (instance == null) {
       instance = new AnimatedMessagePanel();
    }
    return instance;
  } 
  public AnimatedMessagePanel() {
  //init();
    setWidthAndHeight();
  }
  public void init() {
    offscreen = createImage(width, height);
    og = offscreen.getGraphics();
    //g2 = (Graphics2D)og;
  }
  public void setWidthAndHeight() {
    setPreferredSize(new Dimension(width, height));
    setMinimumSize(new Dimension(width, height));
    setMaximumSize(new Dimension(width, height));
  }
  
  public void setWidthAndHeight(int width, int height) {
     this.width = width;
     this.height = height;
     setWidthAndHeight();
  }
  
  public void update(Graphics g) {
    if((offscreen != null) && (og != null))
      paint(g);
  }
  public void paint(Graphics g) {
    if((offscreen != null) && (og != null)) {
      g.drawImage(offscreen, 0, 0, null);
    }
  }
  
  public void run() {
    boolean setup = true;
    while(setup) {
      try { animator.sleep(1000); } catch(Exception e) { }
      if((offscreen != null) && (og != null)) {
        paintBG();
        printMessages();
        repaint();
        setup = false;
      }
      else {
        offscreen = createImage(width, height);
        if(offscreen != null) {
          og = offscreen.getGraphics();
          System.out.println("\n\nget og object: " + og);
          printMessages();
        }
      }
      //while(true) {
        //just loop to check for resize of component
      //  try { animator.sleep(2000); } catch(Exception e) { }
      //  if(!currentlyScrolling) {
      //    repaint();  
      //  }
      //}
      
    }
  }
  
  private void paintBG() {
    og.setColor(Color.white);
    og.fillRect(0, 0, getWidth(), getHeight());
    //og.setColor(Color.black);
  }
  
  public void start() {
    if(started) return;
    animator = new Thread(this);
    try { animator.sleep(1500); } catch(Exception e) { }
    animator.start();
    started = true;
  }
  
  public void alertNewMessage(String message) {
    addToMessageQue(message);
  }
  
  public void printMessages() {
    
      try {
          Runnable runner = new Runnable () {
            public void run () {
          
              AnimatedMessagePanel.getInstance().setCurrentlyScrolling(true);
   Graphics2D g2 = (Graphics2D)og;
              
   int linecount = 1;
   StringTokenizer st1 = new StringTokenizer(messageQue[0]);
     String text1 = "";
     String testtext1 = "";
     String prodtext1 = "";
     while(st1.hasMoreTokens()) {
       text1 = st1.nextToken();
       testtext1 += text1 + " ";
       FontRenderContext frc1 = g2.getFontRenderContext();                 
       TextLayout t11 = new TextLayout(testtext1, font, frc1);
       int sw1 = (int) t11.getBounds().getWidth();
       if(sw1 > (getWidth() - 40)) {
        linecount++;
        testtext1 = "";
        prodtext1 = text1;
       }
       else prodtext1 += text1 + " ";
     }
     
              
            
  for (int k = -(15)*(linecount-1); k <= 15; k++) {
    paintBG();
      int y = k;
      og.setColor(Color.black);
      for(int j = 0; j < messageQue.length; j++) {
        if(messageQue[j].length() != 0) {
        StringTokenizer st = new StringTokenizer(messageQue[j]);
        String text = "";
        String testtext = "";
        String prodtext = "";
        while(st.hasMoreTokens()) {
          text = st.nextToken();
          testtext += text + " ";
            FontRenderContext frc = g2.getFontRenderContext();                 
            TextLayout t1 = new TextLayout(testtext, font, frc);
            int sw = (int) t1.getBounds().getWidth();
            if(sw > (getWidth() - 40)) {
            og.drawString(prodtext, 10, y);
            y += 12;
            testtext = "";
            prodtext = text;
            }
            else prodtext += text + " ";
          }
        og.drawString(prodtext, 10, y);
          y += 18;
          if(y > getHeight()) break;
        }
      }
      repaint();
      try { Thread.sleep(50); } catch(Exception de) { }
  }
   AnimatedMessagePanel.getInstance().setCurrentlyScrolling(false);
   AnimatedMessagePanel.getInstance().checkForMessagesWaiting();
    
            }
        };
        new Thread (runner, "printMessage.run").start ();
      }
      catch ( Exception e) { }
  }
  
  private void addToMessageQue(String message) {
  if(isCurrentlyScrolling()) putMessageInWaitingQue(message);
  else {
      //first move all messages down one then add then new message to the top
      for(int i = (messageQue.length - 2); i >= 0 ; i--)  
        messageQue[i+1] = messageQue[i]; 
      messageQue[0] = message; 
      printMessages();
  }
  }
  
  private void putMessageInWaitingQue(String message) {
  for(int i = 0; i < messageWaitingQue.length; i++) {
    if(messageWaitingQue[i].length() == 0) { //nothing there, so it"s open
      messageWaitingQue[i] = message;
        break;
    }
  }
  }
  
  private boolean messageQueEmpty() {
    return  (messageWaitingQue[0].length() == 0);
  }
  
  private String getNextMessageInWaitingQue() {
  String returnStr = messageWaitingQue[0];
  adjustMessageWaitingQue();
  return returnStr;
  }
  
  private void adjustMessageWaitingQue() {
  for(int i = 0; i < (messageWaitingQue.length - 1); i++) 
    messageWaitingQue[i] = messageWaitingQue[i + 1];
    messageWaitingQue[(messageWaitingQue.length - 1)] = "";
  }
  
  private void checkForMessagesWaiting() {
    if(!messageQueEmpty()) {
    addToMessageQue(getNextMessageInWaitingQue());
  }
  }
  public void clearMessageQues() {
    for(int i = 0; i < messageQue.length; i++) messageQue[i] = ""; 
    for(int j = 0; j < messageWaitingQue.length; j++) messageWaitingQue[j] = "";
    printMessages();
  }
}



Animated PasswordField

   
/**
 *   Arsenal Real-Time Collaboration Server Project
 *   Copyright (C) 2003  Michael Burnside, Arsenal Project
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***************************************************************** 
 *    $Header: /cvs/coolcollaborator/prod/coolcollaborator/prod/util/src/com/arsenal/util/AnimatedPasswordField.java,v 1.1.1.1 2006/01/12 04:54:02 mburnside Exp $ 
 *     
 *    File: $Workfile: AnimatedPasswordField.java $ 
 *     
 *    Description: 
 *     
 *    
 *     
 *    @author      michael@michaelburnside.ru (arsenal-1) 
 *    @author      Michael Burnside 
 *    @version     %I%, %G% 
 *    @since       1.0 
 *     
 */
import java.io.File;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AnimatedPasswordField extends JPanel implements FocusListener {
        
        Font font = new Font("Arial", Font.PLAIN, 10);
        Color darkSlateGray = new Color(49,79,79);
        Color dimGray = new Color(105,105,105);
        Color slateGray = new Color(112,138,144);
        Color lightSlateGray = new Color(119,136,153);
        Color gray = new Color(190,190,190);
        Color lightGray = new Color(211,211,211);
        Color[] colors = { Color.black, darkSlateGray, dimGray, slateGray,
                lightSlateGray, gray, lightGray, Color.white };
        
  private JPasswordField textField = new JPasswordField();
        private JLabel label = new JLabel();
        private int fadeSpeed = 50;
        private boolean animate = false;
        private boolean allowFade = false;
        private boolean fadeOut = false;
        private boolean fadeIn = false;
  private Color foreground = Color.black;
  public void setDefaultForeground(Color foreground) { this.foreground = foreground; }
        private boolean allowAnimate = true; // we will animate
  
  public AnimatedPasswordField(String labelText, boolean useBgImage, Color defaultForeground, boolean allowAnimate) { 
    this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
          label.setText(labelText);
    textField.addFocusListener(this);
          label.setBackground(colors[0]);
    textField.setBackground(colors[0]);
    this.foreground = defaultForeground;
          this.allowAnimate = allowAnimate;
          label.setForeground(foreground);
    textField.setForeground(foreground);
          add(label);
    add(textField);
      if(allowAnimate) 
          runThread.start();
        if(allowFade) {
          fadeInThread.start();
          fadeOutThread.start();
        }
          setOpaque(false);
  }
  
  public AnimatedPasswordField(String labelText, boolean useBgImage, Color defaultForeground, boolean allowAnimate, boolean allowFade) { 
      this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
            label.setText(labelText);
      textField.addFocusListener(this);
            label.setBackground(colors[0]);
      textField.setBackground(colors[0]);
      this.foreground = defaultForeground;
            this.allowAnimate = allowAnimate;
            this.allowFade = allowFade;
            label.setForeground(foreground);
      textField.setForeground(foreground);
            add(label);
      add(textField);
        if(allowAnimate) 
            runThread.start();
          if(allowFade) {
            fadeInThread.start();
            fadeOutThread.start();
          }
            setOpaque(false);
    } 
        
        
        private Thread runThread = new Thread(
          new  Runnable() {    
            public void run() {
              while(true) {
                try { runThread.sleep(100); } catch(Exception e) { }       
                if(animate) {
                  for(int i = 0; i < colors.length; i++) {
                    label.setForeground(colors[i]);
                    try { runThread.sleep(20); } catch(Exception e) { }
                  }
                  try { runThread.sleep(100); } catch(Exception e) { }
                  for(int i = colors.length -1 ; i >= 0; i--) {
                    label.setForeground(colors[i]);      
                    try { runThread.sleep(20); } catch(Exception le) { }
                  }
                } // end if animate
                label.setForeground(foreground); 
              } //end while
            }
          }
        );
     
        
        private Thread fadeInThread = new Thread(
          new  Runnable() {    
            public void run() {
               while(true) {
                 if(fadeIn) {     
                   fadeIn();
                   fadeIn = false;
                 }
                 try { fadeInThread.sleep(fadeSpeed); } catch(Exception le) { }
               }
            }
          }
        );
        
        
        private Thread fadeOutThread = new Thread(
          new  Runnable() {    
            public void run() {
               while(true) {
                 if(fadeOut) {
                   fadeOut();
                   fadeOut = false;
                 }
                 try { fadeOutThread.sleep(fadeSpeed); } catch(Exception le) { }
               }
            }
          }
        );
        
  public void focusGained(FocusEvent e) 
  {
        //if(allowAnimate) fadeIn();
        animate = true;
        if(allowFade) {
          fadeIn = true;
          fadeOut = false;
        }
        else {
         textField.setBackground(Color.white);
         textField.setForeground(Color.black);
        }
  }
  public void focusLost(FocusEvent e) 
  {
        //if(allowAnimate) fadeOut();
        animate = false;
        if(allowFade) {
          fadeOut = true;
          fadeIn = false;
          try { runThread.sleep(50); } catch(Exception le) { }
        }
        else {
         textField.setBackground(Color.black);
         textField.setForeground(Color.white);
        }
  }
        /**
         *
         * disable the components on this panel
         *
         */
  public void setInputsDisabled() 
  {
           setInputsEnabled(false);
  }
        /**
         *
         * enable the components on this panel
         *
         */
  public void setInputsEnabled() 
  {
           setInputsEnabled(true);
  }
        /**
         *
         * enable or disable the components on this panel
         *
         * @param enable or disable
         *
         */
  public void setInputsEnabled(boolean enable) 
  {
     textField.setEnabled(enable);
     //label.setEnabled(enable);
           if(!enable) animate = false;
  }
        /**
         *
         * are the inputs enabled
         *
         * @returns boolean
         *
         */
  public boolean areInputsEnabled() 
  {
     return textField.isEnabled();
  }        
        /**
         *
         * Sets the label"s maximum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */         
        public void setLabelMaximumSize(int width, int height) {
           label.setMaximumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the label"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setLabelMinimumSize(int width, int height) {
           label.setMinimumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the label"s preferred size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setLabelPreferredSize(int width, int height) {
           label.setPreferredSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s maximum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setTextFieldMaximumSize(int width, int height) {
           textField.setMaximumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setTextFieldMinimumSize(int width, int height) {
           textField.setMinimumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s preferred size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setTextFieldPreferredSize(int width, int height) {
           textField.setPreferredSize(new Dimension(width, height));       
        }
        /**
         *
         * Gets the text field"s value
         *
         * @return the text field value after trim()
         *
         */        
        public String getValue() {
           return textField.getText().trim();       
        }
        /**
         *
         * gets the label instance
         *
         * @return jlabel component of this class
         *
         */        
        public JLabel getLabel() {
           return label;       
        }
        /**
         *
         * gets the text field instance
         *
         * @return textfield component of this class
         *
         */        
        public JTextField getTextField() {
           return textField;       
        }
        
        public void setText(String text) {
           textField.setText(text);
        }
        
        private void fadeIn() {
          textField.setForeground(Color.black);
          for(int i = 0; i < colors.length; i++) {
            textField.setBackground(colors[i]);
            try { Thread.sleep(fadeSpeed); } catch(Exception e) { }
          }                
        }
        
        private void fadeOut() {
          textField.setForeground(Color.white);
          for(int i = colors.length -1 ; i >= 0; i--) {
            textField.setBackground(colors[i]); 
            try { Thread.sleep(fadeSpeed); } catch(Exception le) { }
          }                
        }
        
}



Animated TextField

   
/**
 *   Arsenal Real-Time Collaboration Server Project
 *   Copyright (C) 2003  Michael Burnside, Arsenal Project
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***************************************************************** 
 *    $Header: /cvs/coolcollaborator/prod/coolcollaborator/prod/util/src/com/arsenal/util/AnimatedTextField.java,v 1.1.1.1 2006/01/12 04:54:02 mburnside Exp $ 
 *     
 *    File: $Workfile: AnimatedTextField.java $ 
 *     
 *    Description: 
 *     
 *    
 *     
 *    @author      michael@michaelburnside.ru (arsenal-1) 
 *    @author      Michael Burnside 
 *    @version     %I%, %G% 
 *    @since       1.0 
 *     
 */
import java.io.File;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AnimatedTextField extends JPanel implements FocusListener {
        
        Font font = new Font("Arial", Font.PLAIN, 10);
        Color darkSlateGray = new Color(49,79,79);
        Color dimGray = new Color(105,105,105);
        Color slateGray = new Color(112,138,144);
        Color lightSlateGray = new Color(119,136,153);
        Color gray = new Color(190,190,190);
        Color lightGray = new Color(211,211,211);
        Color[] colors = { Color.black, darkSlateGray, dimGray, slateGray,
                lightSlateGray, gray, lightGray, Color.white };
        
  private JTextField textField = new JTextField();
        private JLabel label = new JLabel();
        private int fadeSpeed = 50;
        private boolean animate = false;
        private boolean allowFade = false;
        private boolean fadeOut = false;
        private boolean fadeIn = false;
  private Color foreground = Color.black;
  public void setDefaultForeground(Color foreground) { this.foreground = foreground; }
        private boolean allowAnimate = true; // we will animate
  
  public AnimatedTextField(String labelText, boolean useBgImage, Color defaultForeground, boolean allowAnimate) { 
    this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
          label.setText(labelText);
    textField.addFocusListener(this);
          label.setBackground(colors[0]);
    textField.setBackground(colors[0]);
    this.foreground = defaultForeground;
          this.allowAnimate = allowAnimate;
          label.setForeground(foreground);
    textField.setForeground(foreground);
          add(label);
    add(textField);
          if(allowAnimate) 
            runThread.start();
          if(allowFade) {
            fadeInThread.start();
            fadeOutThread.start();
          }
          setOpaque(false);
  }
  
  public AnimatedTextField(String labelText, boolean useBgImage, Color defaultForeground, boolean allowAnimate, boolean allowFade) { 
      this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
            label.setText(labelText);
      textField.addFocusListener(this);
            label.setBackground(colors[0]);
      textField.setBackground(colors[0]);
      this.foreground = defaultForeground;
            this.allowAnimate = allowAnimate;
            this.allowFade = allowFade;
            label.setForeground(foreground);
      textField.setForeground(foreground);
            add(label);
      add(textField);
            if(allowAnimate) 
              runThread.start();
            if(allowFade) {
              fadeInThread.start();
              fadeOutThread.start();
            }
            setOpaque(false);
    } 
  
    public void addActionListener(ActionListener actionListener) {
        textField.addActionListener(actionListener);
     }
        
        
        private Thread runThread = new Thread(
          new  Runnable() {    
            public void run() {
              while(true) {
                try { runThread.sleep(100); } catch(Exception e) { }       
                if(animate) {
                  for(int i = 0; i < colors.length; i++) {
                    label.setForeground(colors[i]);
                    try { runThread.sleep(20); } catch(Exception e) { }
                  }
                  try { runThread.sleep(100); } catch(Exception e) { }
                  for(int i = colors.length -1 ; i >= 0; i--) {
                    label.setForeground(colors[i]);      
                    try { runThread.sleep(20); } catch(Exception le) { }
                  }
                } // end if animate
                label.setForeground(foreground); 
              } //end while
            }
          }
        );
     
        
        private Thread fadeInThread = new Thread(
          new  Runnable() {    
            public void run() {
               while(true) {
                 if(fadeIn) {     
                   fadeIn();
                   fadeIn = false;
                 }
                 try { fadeInThread.sleep(fadeSpeed); } catch(Exception le) { }
               }
            }
          }
        );
        
        
        private Thread fadeOutThread = new Thread(
          new  Runnable() {    
            public void run() {
               while(true) {
                 if(fadeOut) {
                   fadeOut();
                   fadeOut = false;
                 }
                 try { fadeOutThread.sleep(fadeSpeed); } catch(Exception le) { }
               }
            }
          }
        );
        
  public void focusGained(FocusEvent e) 
  {
           //if(allowAnimate) fadeIn();
           animate = true;
           if(allowFade) {
             fadeIn = true;
             fadeOut = false;
           }
           else {
             textField.setBackground(Color.white);
             textField.setForeground(Color.black);
           }
  }
  public void focusLost(FocusEvent e) 
  {
           //if(allowAnimate) fadeOut();
           animate = false;
           if(allowFade) {
             fadeOut = true;
             fadeIn = false;
             try { runThread.sleep(50); } catch(Exception le) { }
           }
           else {
             textField.setBackground(Color.black);
             textField.setForeground(Color.white);
           }
  }
        /**
         *
         * disable the components on this panel
         *
         */
  public void setInputsDisabled() 
  {
           setInputsEnabled(false);
  }
        /**
         *
         * enable the components on this panel
         *
         */
  public void setInputsEnabled() 
  {
           setInputsEnabled(true);
  }
        /**
         *
         * enable or disable the components on this panel
         *
         * @param enable or disable
         *
         */
  public void setInputsEnabled(boolean enable) 
  {
     textField.setEnabled(enable);
     //label.setEnabled(enable);
           if(!enable) animate = false;
  }
        /**
         *
         * are the inputs enabled
         *
         * @returns boolean
         *
         */
  public boolean areInputsEnabled() 
  {
     return textField.isEnabled();
  }        
        /**
         *
         * Sets the label"s maximum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */         
        public void setLabelMaximumSize(int width, int height) {
           label.setMaximumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the label"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setLabelMinimumSize(int width, int height) {
           label.setMinimumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the label"s preferred size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setLabelPreferredSize(int width, int height) {
           label.setPreferredSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s maximum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setTextFieldMaximumSize(int width, int height) {
           textField.setMaximumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s minimum size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */
        public void setTextFieldMinimumSize(int width, int height) {
           textField.setMinimumSize(new Dimension(width, height));       
        }
        /**
         *
         * Sets the text field"s preferred size
         *
         * @param width width, in pixels
         * @param height height, in pixels
         *
         */        
        public void setTextFieldPreferredSize(int width, int height) {
           textField.setPreferredSize(new Dimension(width, height));       
        }
        /**
         *
         * Gets the text field"s value
         *
         * @return the text field value after trim()
         *
         */        
        public String getValue() {
           return textField.getText().trim();       
        }
        /**
         *
         * gets the label instance
         *
         * @return jlabel component of this class
         *
         */        
        public JLabel getLabel() {
           return label;       
        }
        /**
         *
         * gets the text field instance
         *
         * @return textfield component of this class
         *
         */        
        public JTextField getTextField() {
           return textField;       
        }
        
        public void setText(String text) {
           textField.setText(text);
        }
        
        private void fadeIn() {
          textField.setForeground(Color.black);
          for(int i = 0; i < colors.length; i++) {
            textField.setBackground(colors[i]);
            try { Thread.sleep(fadeSpeed); } catch(Exception e) { }
          }                
        }
        
        private void fadeOut() {
          textField.setForeground(Color.white);
          for(int i = colors.length -1 ; i >= 0; i--) {
            textField.setBackground(colors[i]); 
            try { Thread.sleep(fadeSpeed); } catch(Exception le) { }
          }
        }
        
}



Animation: bounce

    
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.ruponentAdapter;
import java.awt.event.ruponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.text.NumberFormat;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Bouncer extends JPanel implements Runnable {
  private boolean trucking = true;
  private long[] previousTimes; // milliseconds
  private int previousIndex;
  private boolean previousFilled;
  private double frameRate; // frames per second
  private Image image;
  public static void main(String[] args) {
    final Bouncer bouncer = new Bouncer();
    Frame f = new AnimationFrame(bouncer);
    f.setFont(new Font("Serif", Font.PLAIN, 12));
    f.setSize(200, 200);
    Panel controls = new Panel();
    controls.add(bouncer.createCheckbox("Anti.", Bouncer.ANTIALIASING));
    controls.add(bouncer.createCheckbox("Trans.", Bouncer.TRANSFORM));
    controls.add(bouncer.createCheckbox("Gradient", Bouncer.GRADIENT));
    controls.add(bouncer.createCheckbox("Outline", Bouncer.OUTLINE));
    controls.add(bouncer.createCheckbox("Dotted", Bouncer.DOTTED));
    controls.add(bouncer.createCheckbox("Axes", Bouncer.AXES));
    controls.add(bouncer.createCheckbox("Clip", Bouncer.CLIP));
    f.add(controls, BorderLayout.NORTH);
    f.setVisible(true);
  }
  // Tweakable variables
  private boolean mAntialiasing, mGradient, mOutline;
  private boolean mTransform, mDotted, mAxes, mClip;
  // ...and the constants that represent them. See setSwitch().
  public static final int ANTIALIASING = 0;
  public static final int GRADIENT = 1;
  public static final int OUTLINE = 2;
  public static final int TRANSFORM = 3;
  public static final int DOTTED = 4;
  public static final int AXES = 5;
  public static final int CLIP = 6;
  private float[] mPoints;
  private float[] mDeltas;
  private float mTheta;
  private int mN;
  private Shape mClipShape;
  public Bouncer() {
    previousTimes = new long[128];
    previousTimes[0] = System.currentTimeMillis();
    previousIndex = 1;
    previousFilled = false;
    mN = 38;
    mPoints = new float[mN];
    mDeltas = new float[mN];
    Random random = new Random();
    for (int i = 0; i < mN; i++) {
      mPoints[i] = random.nextFloat() * 500;
      mDeltas[i] = random.nextFloat() * 3;
    }
    addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent ce) {
        Dimension d = getSize();
        for (int i = 0; i < mN; i++) {
          int limit = ((i % 2) == 0) ? d.width : d.height;
          if (mPoints[i] < 0)
            mPoints[i] = 0;
          else if (mPoints[i] >= limit)
            mPoints[i] = limit - 1;
        }
      }
    });
  }
  public void setSwitch(int item, boolean value) {
    switch (item) {
    case ANTIALIASING:
      mAntialiasing = value;
      break;
    case GRADIENT:
      mGradient = value;
      break;
    case OUTLINE:
      mOutline = value;
      break;
    case TRANSFORM:
      mTransform = value;
      break;
    case DOTTED:
      mDotted = value;
      break;
    case AXES:
      mAxes = value;
      break;
    case CLIP:
      mClip = value;
      break;
    default:
      break;
    }
  }
  protected Checkbox createCheckbox(String label, final int item) {
    Checkbox check = new Checkbox(label);
    check.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        setSwitch(item, (ie.getStateChange() == ie.SELECTED));
      }
    });
    return check;
  }
  public void timeStep() {
    Dimension d = getSize();
    for (int i = 0; i < mN; i++) {
      float value = mPoints[i] + mDeltas[i];
      int limit = ((i % 2) == 0) ? d.width : d.height;
      if (value < 0 || value > limit) {
        mDeltas[i] = -mDeltas[i];
        mPoints[i] += mDeltas[i];
      } else
        mPoints[i] = value;
    }
    mTheta += Math.PI / 192;
    if (mTheta > (2 * Math.PI))
      mTheta -= (2 * Math.PI);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    setAntialiasing(g2);
    setClip(g2);
    setTransform(g2);
    Shape shape = createShape();
    setPaint(g2);
    g2.fill(shape);
    if (mOutline) {
      setStroke(g2);
      g2.setPaint(Color.blue);
      g2.draw(shape);
    }
    drawAxes(g2);
  }
  protected void setAntialiasing(Graphics2D g2) {
    if (mAntialiasing == false)
      return;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
  }
  protected void setClip(Graphics2D g2) {
    if (mClip == false)
      return;
    if (mClipShape == null) {
      Dimension d = getSize();
      FontRenderContext frc = g2.getFontRenderContext();
      Font font = new Font("Serif", Font.PLAIN, 144);
      String s = "Java Source and Support!";
      GlyphVector gv = font.createGlyphVector(frc, s);
      Rectangle2D bounds = font.getStringBounds(s, frc);
      mClipShape = gv.getOutline(
          (d.width - (float) bounds.getWidth()) / 2,
          (d.height + (float) bounds.getHeight()) / 2);
    }
    g2.clip(mClipShape);
  }
  protected void setTransform(Graphics2D g2) {
    if (mTransform == false)
      return;
    Dimension d = getSize();
    g2.rotate(mTheta, d.width / 2, d.height / 2);
  }
  protected Shape createShape() {
    GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD,
        mPoints.length);
    path.moveTo(mPoints[0], mPoints[1]);
    for (int i = 2; i < mN; i += 6)
      path.curveTo(mPoints[i], mPoints[i + 1], mPoints[i + 2],
          mPoints[i + 3], mPoints[i + 4], mPoints[i + 5]);
    path.closePath();
    return path;
  }
  protected void setPaint(Graphics2D g2) {
    if (mGradient) {
      GradientPaint gp = new GradientPaint(0, 0, Color.yellow, 50, 25,
          Color.red, true);
      g2.setPaint(gp);
    } else
      g2.setPaint(Color.orange);
  }
  protected void setStroke(Graphics2D g2) {
    if (mDotted == false)
      return;
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_ROUND, 10, new float[] { 4, 4 }, 0);
    g2.setStroke(stroke);
  }
  protected void drawAxes(Graphics2D g2) {
    if (mAxes == false)
      return;
    g2.setPaint(getForeground());
    g2.setStroke(new BasicStroke());
    Dimension d = getSize();
    int side = 20;
    int arrow = 4;
    int w = d.width / 2, h = d.height / 2;
    g2.drawLine(w - side, h, w + side, h);
    g2.drawLine(w + side - arrow, h - arrow, w + side, h);
    g2.drawLine(w, h - side, w, h + side);
    g2.drawLine(w + arrow, h + side - arrow, w, h + side);
  }
  public void run() {
    while (trucking) {
      render();
      timeStep();
      calculateFrameRate();
    }
  }
  protected void render() {
    Graphics g = getGraphics();
    if (g != null) {
      Dimension d = getSize();
      if (checkImage(d)) {
        Graphics imageGraphics = image.getGraphics();
        imageGraphics.setColor(getBackground());
        imageGraphics.fillRect(0, 0, d.width, d.height);
        imageGraphics.setColor(getForeground());
        paint(imageGraphics);
        g.drawImage(image, 0, 0, null);
        imageGraphics.dispose();
      }
      g.dispose();
    }
  }
  // Offscreen image.
  protected boolean checkImage(Dimension d) {
    if (d.width == 0 || d.height == 0)
      return false;
    if (image == null || image.getWidth(null) != d.width
        || image.getHeight(null) != d.height) {
      image = createImage(d.width, d.height);
    }
    return true;
  }
  protected void calculateFrameRate() {
    // Measure the frame rate
    long now = System.currentTimeMillis();
    int numberOfFrames = previousTimes.length;
    double newRate;
    // Use the more stable method if a history is available.
    if (previousFilled)
      newRate = (double) numberOfFrames
          / (double) (now - previousTimes[previousIndex]) * 1000.0;
    else
      newRate = 1000.0 / (double) (now - previousTimes[numberOfFrames - 1]);
    firePropertyChange("frameRate", frameRate, newRate);
    frameRate = newRate;
    // Update the history.
    previousTimes[previousIndex] = now;
    previousIndex++;
    if (previousIndex >= numberOfFrames) {
      previousIndex = 0;
      previousFilled = true;
    }
  }
  public double getFrameRate() {
    return frameRate;
  }
  // Property change support.
  private transient AnimationFrame mRateListener;
  public void setRateListener(AnimationFrame af) {
    mRateListener = af;
  }
  public void firePropertyChange(String name, double oldValue, double newValue) {
    mRateListener.rateChanged(newValue);
  }
}
class AnimationFrame extends JFrame {
  private Label mStatusLabel;
  private NumberFormat mFormat;
  public AnimationFrame(Bouncer ac) {
    super();
    setLayout(new BorderLayout());
    add(ac, BorderLayout.CENTER);
    add(mStatusLabel = new Label(), BorderLayout.SOUTH);
    // Create a number formatter.
    mFormat = NumberFormat.getInstance();
    mFormat.setMaximumFractionDigits(1);
    // Listen for the frame rate changes.
    ac.setRateListener(this);
    // Kick off the animation.
    Thread t = new Thread(ac);
    t.start();
  }
  public void rateChanged(double frameRate) {
    mStatusLabel.setText(mFormat.format(frameRate) + " fps");
  }
}



Animator Demo

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * @(#)Animator.java  1.5 95/11/29 Herb Jellinek
 *
 * Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted.
 * Please refer to the file http://java.sun.ru/copy_trademarks.html
 * for further important copyright and trademark information and to
 * http://java.sun.ru/licensing.html for further important licensing
 * information for the Java (tm) Technology.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.image.ImageProducer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
 * An applet that plays a sequence of images, as a loop or a one-shot. Can have
 * a soundtrack and/or sound effects tied to individual frames.
 * 
 * @author Herb Jellinek
 * @version 1.5, 29 Nov 1995
 */
public class Animator extends Applet implements Runnable {
  /**
   * The images, in display order (Images).
   */
  Vector images = null;
  /**
   * Duration of each image (Integers, in milliseconds).
   */
  Hashtable durations = null;
  /**
   * Sound effects for each image (AudioClips).
   */
  Hashtable sounds = null;
  /**
   * Position of each image (Points).
   */
  Hashtable positions = null;
  /**
   * MediaTracker "class" ID numbers.
   */
  static final int STARTUP_ID = 0;
  static final int BACKGROUND_ID = 1;
  static final int ANIMATION_ID = 2;
  /**
   * Start-up image URL, if any.
   */
  URL startUpImageURL = null;
  /**
   * Start-up image, if any.
   */
  Image startUpImage = null;
  /**
   * Background image URL, if any.
   */
  URL backgroundImageURL = null;
  /**
   * Background image, if any.
   */
  Image backgroundImage = null;
  /**
   * The soundtrack"s URL.
   */
  URL soundtrackURL = null;
  /**
   * The soundtrack.
   */
  AudioClip soundtrack;
  /**
   * Largest width.
   */
  int maxWidth = 0;
  /**
   * Largest height.
   */
  int maxHeight = 0;
  /**
   * Was there a problem loading the current image?
   */
  boolean imageLoadError = false;
  /**
   * The directory or URL from which the images are loaded
   */
  URL imageSource = null;
  /**
   * The directory or URL from which the sounds are loaded
   */
  URL soundSource = null;
  /**
   * The thread animating the images.
   */
  Thread engine = null;
  /**
   * The current loop slot - index into "images."
   */
  int frameNum;
  /**
   * frameNum as an Object - suitable for use as a Hashtable key.
   */
  Integer frameNumKey;
  /**
   * The current X position (for painting).
   */
  int xPos = 0;
  /**
   * The current Y position (for painting).
   */
  int yPos = 0;
  /**
   * The default number of milliseconds to wait between frames.
   */
  public static final int defaultPause = 3900;
  /**
   * The global delay between images, which can be overridden by the PAUSE
   * parameter.
   */
  int globalPause = defaultPause;
  /**
   * Whether or not the thread has been paused by the user.
   */
  boolean userPause = false;
  /**
   * Repeat the animation? If false, just play it once.
   */
  boolean repeat;
  /**
   * The offscreen image, used in double buffering
   */
  Image offScrImage;
  /**
   * The offscreen graphics context, used in double buffering
   */
  Graphics offScrGC;
  /**
   * The MediaTracker we use to load our images.
   */
  MediaTracker tracker;
  /**
   * Can we paint yet?
   */
  boolean loaded = false;
  /**
   * Was there an initialization error?
   */
  boolean error = false;
  /**
   * What we call an image file in messages.
   */
  final static String imageLabel = "image";
  /**
   * What we call a sound file in messages.
   */
  final static String soundLabel = "sound";
  /**
   * Print silly debugging info?
   */
  final boolean debug = false;
  /**
   * Applet info.
   */
  public String getAppletInfo() {
    return "Animator v1.5, by Herb Jellinek";
  }
  /**
   * Parameter info.
   */
  public String[][] getParameterInfo() {
    String[][] info = { { "imagesource", "URL", "a directory" },
        { "startup", "URL", "displayed at startup" },
        { "background", "URL", "displayed as background" },
        { "startimage", "int", "start index" },
        { "endimage", "int", "end index" },
        { "namepattern", "URL", "used to generate indexed names" },
        { "pause", "int", "milliseconds" },
        { "pauses", "ints", "milliseconds" },
        { "repeat", "boolean", "repeat or not" },
        { "positions", "coordinates", "path" },
        { "soundsource", "URL", "audio directory" },
        { "soundtrack", "URL", "background music" },
        { "sounds", "URLs", "audio samples" }, };
    return info;
  }
  /**
   * Print silly debugging info.
   */
  void dbg(String s) {
    if (debug) {
      System.out.println("> " + s);
    }
  }
  /**
   * Local version of getParameter for debugging purposes.
   */
  public String getParameter(String key) {
    String result = super.getParameter(key);
    dbg("getParameter(" + key + ") = " + result);
    return result;
  }
  final int setFrameNum(int newFrameNum) {
    frameNumKey = new Integer(frameNum = newFrameNum);
    return frameNum;
  }
  void updateMaxDims(Dimension dim) {
    maxWidth = Math.max(dim.width, maxWidth);
    maxHeight = Math.max(dim.height, maxHeight);
    dbg("New width = " + maxWidth + ", height = " + maxHeight);
  }
  /**
   * Parse the IMAGES parameter. It looks like 1|2|3|4|5, etc., where each
   * number (item) names a source image.
   * 
   * @return a Vector of (URL) image file names.
   */
  Vector parseImages(String attr) throws MalformedURLException {
    Vector result = new Vector(10);
    for (int i = 0; i < attr.length();) {
      int next = attr.indexOf("|", i);
      if (next == -1)
        next = attr.length();
      String file = attr.substring(i, next);
      result.addElement(new URL(imageSource, "T" + file + ".gif"));
      i = next + 1;
    }
    return result;
  }
  /**
   * Fetch the images named in the argument, updating maxWidth and maxHeight
   * as we go. Is restartable.
   * 
   * @param images
   *            a Vector of URLs
   * @return true if all went well, false otherwise.
   */
  boolean fetchImages(Vector images) {
    int i;
    int size = images.size();
    for (i = 0; i < size; i++) {
      Object o = images.elementAt(i);
      if (o instanceof URL) {
        URL url = (URL) o;
        tellLoadingMsg(url, imageLabel);
        Image im = getImage(url);
        tracker.addImage(im, ANIMATION_ID);
        images.setElementAt(im, i);
      }
    }
    try {
      tracker.waitForID(ANIMATION_ID);
    } catch (InterruptedException e) {
    }
    if (tracker.isErrorID(ANIMATION_ID)) {
      return false;
    }
    for (i = 0; i < size; i++) {
      updateMaxDims(getImageDimensions((Image) images.elementAt(i)));
    }
    return true;
  }
  /**
   * Parse the SOUNDS parameter. It looks like train.au||hello.au||stop.au,
   * etc., where each item refers to a source image. Empty items mean that the
   * corresponding image has no associated sound.
   * 
   * @return a Hashtable of SoundClips keyed to Integer frame numbers.
   */
  Hashtable parseSounds(String attr, Vector images)
      throws MalformedURLException {
    Hashtable result = new Hashtable();
    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < attr.length();) {
      if (imageNum >= numImages)
        break;
      int next = attr.indexOf("|", i);
      if (next == -1)
        next = attr.length();
      String sound = attr.substring(i, next);
      if (sound.length() != 0) {
        result.put(new Integer(imageNum), new URL(soundSource, sound));
      }
      i = next + 1;
      imageNum++;
    }
    return result;
  }
  /**
   * Fetch the sounds named in the argument. Is restartable.
   * 
   * @return URL of the first bogus file we hit, null if OK.
   */
  URL fetchSounds(Hashtable sounds) {
    for (Enumeration e = sounds.keys(); e.hasMoreElements();) {
      Integer num = (Integer) e.nextElement();
      Object o = sounds.get(num);
      if (o instanceof URL) {
        URL file = (URL) o;
        tellLoadingMsg(file, soundLabel);
        try {
          sounds.put(num, getAudioClip(file));
        } catch (Exception ex) {
          return file;
        }
      }
    }
    return null;
  }
  /**
   * Parse the PAUSES parameter. It looks like 1000|500|||750, etc., where
   * each item corresponds to a source image. Empty items mean that the
   * corresponding image has no special duration, and should use the global
   * one.
   * 
   * @return a Hashtable of Integer pauses keyed to Integer frame numbers.
   */
  Hashtable parseDurations(String attr, Vector images) {
    Hashtable result = new Hashtable();
    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < attr.length();) {
      if (imageNum >= numImages)
        break;
      int next = attr.indexOf("|", i);
      if (next == -1)
        next = attr.length();
      if (i != next - 1) {
        int duration = Integer.parseInt(attr.substring(i, next));
        result.put(new Integer(imageNum), new Integer(duration));
      } else {
        result.put(new Integer(imageNum), new Integer(globalPause));
      }
      i = next + 1;
      imageNum++;
    }
    return result;
  }
  /**
   * Parse a String of form xxx@yyy and return a Point.
   */
  Point parsePoint(String s) throws ParseException {
    int atPos = s.indexOf("@");
    if (atPos == -1)
      throw new ParseException("Illegal position: " + s);
    return new Point(Integer.parseInt(s.substring(0, atPos)), Integer
        .parseInt(s.substring(atPos + 1)));
  }
  /**
   * Parse the POSITIONS parameter. It looks like 10@30|11@31|||12@20, etc.,
   * where each item is an X@Y coordinate corresponding to a source image.
   * Empty items mean that the corresponding image has the same position as
   * the preceding one.
   * 
   * @return a Hashtable of Points keyed to Integer frame numbers.
   */
  Hashtable parsePositions(String param, Vector images) throws ParseException {
    Hashtable result = new Hashtable();
    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < param.length();) {
      if (imageNum >= numImages)
        break;
      int next = param.indexOf("|", i);
      if (next == -1)
        next = param.length();
      if (i != next) {
        result.put(new Integer(imageNum), parsePoint(param.substring(i,
            next)));
      }
      i = next + 1;
      imageNum++;
    }
    return result;
  }
  /**
   * Get the dimensions of an image.
   * 
   * @return the image"s dimensions.
   */
  Dimension getImageDimensions(Image im) {
    return new Dimension(im.getWidth(null), im.getHeight(null));
  }
  /**
   * Substitute an integer some number of times in a string, subject to
   * parameter strings embedded in the string. Parameter strings: %N -
   * substitute the integer as is, with no padding. % <digit>, for example %5 -
   * substitute the integer left-padded with zeros to <digits>digits wide. %% -
   * substitute a "%" here.
   * 
   * @param inStr
   *            the String to substitute within
   * @param theInt
   *            the int to substitute.
   */
  String doSubst(String inStr, int theInt) {
    String padStr = "0000000000";
    int length = inStr.length();
    StringBuffer result = new StringBuffer(length);
    for (int i = 0; i < length;) {
      char ch = inStr.charAt(i);
      if (ch == "%") {
        i++;
        if (i == length) {
          result.append(ch);
        } else {
          ch = inStr.charAt(i);
          if (ch == "N") {
            // just stick in the number, unmolested
            result.append(theInt + "");
            i++;
          } else {
            int pad;
            if ((pad = Character.digit(ch, 10)) != -1) {
              // we"ve got a width value
              String numStr = theInt + "";
              String scr = padStr + numStr;
              result.append(scr.substring(scr.length() - pad));
              i++;
            } else {
              result.append(ch);
              i++;
            }
          }
        }
      } else {
        result.append(ch);
        i++;
      }
    }
    return result.toString();
  }
  /**
   * Stuff a range of image names into a Vector.
   * 
   * @return a Vector of image URLs.
   */
  Vector prepareImageRange(int startImage, int endImage, String pattern)
      throws MalformedURLException {
    Vector result = new Vector(Math.abs(endImage - startImage) + 1);
    if (pattern == null) {
      pattern = "T%N.gif";
    }
    if (startImage > endImage) {
      for (int i = startImage; i >= endImage; i--) {
        result.addElement(new URL(imageSource, doSubst(pattern, i)));
      }
    } else {
      for (int i = startImage; i <= endImage; i++) {
        result.addElement(new URL(imageSource, doSubst(pattern, i)));
      }
    }
    return result;
  }
  /**
   * Initialize the applet. Get parameters.
   */
  public void init() {
    tracker = new MediaTracker(this);
    try {
      String param = getParameter("IMAGESOURCE");
      imageSource = (param == null) ? getDocumentBase() : new URL(
          getDocumentBase(), param + "/");
      param = getParameter("PAUSE");
      globalPause = (param != null) ? Integer.parseInt(param)
          : defaultPause;
      param = getParameter("REPEAT");
      repeat = (param == null) ? true
          : (param.equalsIgnoreCase("yes") || param
              .equalsIgnoreCase("true"));
      int startImage = 1;
      int endImage = 1;
      param = getParameter("ENDIMAGE");
      if (param != null) {
        endImage = Integer.parseInt(param);
        param = getParameter("STARTIMAGE");
        if (param != null) {
          startImage = Integer.parseInt(param);
        }
        param = getParameter("NAMEPATTERN");
        images = prepareImageRange(startImage, endImage, param);
      } else {
        param = getParameter("STARTIMAGE");
        if (param != null) {
          startImage = Integer.parseInt(param);
          param = getParameter("NAMEPATTERN");
          images = prepareImageRange(startImage, endImage, param);
        } else {
          param = getParameter("IMAGES");
          if (param == null) {
            showStatus("No legal IMAGES, STARTIMAGE, or ENDIMAGE "
                + "specified.");
            return;
          } else {
            images = parseImages(param);
          }
        }
      }
      param = getParameter("BACKGROUND");
      if (param != null) {
        backgroundImageURL = new URL(imageSource, param);
      }
      param = getParameter("STARTUP");
      if (param != null) {
        startUpImageURL = new URL(imageSource, param);
      }
      param = getParameter("SOUNDSOURCE");
      soundSource = (param == null) ? imageSource : new URL(
          getDocumentBase(), param + "/");
      param = getParameter("SOUNDS");
      if (param != null) {
        sounds = parseSounds(param, images);
      }
      param = getParameter("PAUSES");
      if (param != null) {
        durations = parseDurations(param, images);
      }
      param = getParameter("POSITIONS");
      if (param != null) {
        positions = parsePositions(param, images);
      }
      param = getParameter("SOUNDTRACK");
      if (param != null) {
        soundtrackURL = new URL(soundSource, param);
      }
    } catch (MalformedURLException e) {
      showParseError(e);
    } catch (ParseException e) {
      showParseError(e);
    }
    setFrameNum(0);
  }
  void tellLoadingMsg(String file, String fileType) {
    showStatus("Animator: loading " + fileType + " " + file);
  }
  void tellLoadingMsg(URL url, String fileType) {
    tellLoadingMsg(url.toExternalForm(), fileType);
  }
  void clearLoadingMessage() {
    showStatus("");
  }
  void loadError(String fileName, String fileType) {
    String errorMsg = "Animator: Couldn"t load " + fileType + " "
        + fileName;
    showStatus(errorMsg);
    System.err.println(errorMsg);
    error = true;
    repaint();
  }
  void loadError(URL badURL, String fileType) {
    loadError(badURL.toExternalForm(), fileType);
  }
  void showParseError(Exception e) {
    String errorMsg = "Animator: Parse error: " + e;
    showStatus(errorMsg);
    System.err.println(errorMsg);
    error = true;
    repaint();
  }
  void startPlaying() {
    if (soundtrack != null) {
      soundtrack.loop();
    }
  }
  void stopPlaying() {
    if (soundtrack != null) {
      soundtrack.stop();
    }
  }
  /**
   * Run the animation. This method is called by class Thread.
   * 
   * @see java.lang.Thread
   */
  public void run() {
    Thread me = Thread.currentThread();
    URL badURL;
    me.setPriority(Thread.MIN_PRIORITY);
    if (!loaded) {
      try {
        // ... to do a bunch of loading.
        if (startUpImageURL != null) {
          tellLoadingMsg(startUpImageURL, imageLabel);
          startUpImage = getImage(startUpImageURL);
          tracker.addImage(startUpImage, STARTUP_ID);
          tracker.waitForID(STARTUP_ID);
          if (tracker.isErrorID(STARTUP_ID)) {
            loadError(startUpImageURL, "start-up image");
          }
          Dimension size = getImageDimensions(startUpImage);
          resize(size.width, size.height);
          repaint();
        }
        if (backgroundImageURL != null) {
          tellLoadingMsg(backgroundImageURL, imageLabel);
          backgroundImage = getImage(backgroundImageURL);
          tracker.addImage(backgroundImage, BACKGROUND_ID);
          tracker.waitForID(BACKGROUND_ID);
          if (tracker.isErrorID(BACKGROUND_ID)) {
            loadError(backgroundImageURL, "background image");
          }
          updateMaxDims(getImageDimensions(backgroundImage));
          repaint();
        }
        // Fetch the animation frames
        if (!fetchImages(images)) {
          // Need to add method to MediaTracker to return
          // files that caused errors during loading.
          loadError("an image", imageLabel);
          return;
        }
        if (soundtrackURL != null && soundtrack == null) {
          tellLoadingMsg(soundtrackURL, imageLabel);
          soundtrack = getAudioClip(soundtrackURL);
          if (soundtrack == null) {
            loadError(soundtrackURL, "soundtrack");
            return;
          }
        }
        if (sounds != null) {
          badURL = fetchSounds(sounds);
          if (badURL != null) {
            loadError(badURL, soundLabel);
            return;
          }
        }
        clearLoadingMessage();
        offScrImage = createImage(maxWidth, maxHeight);
        offScrGC = offScrImage.getGraphics();
        offScrGC.setColor(Color.white);
        resize(maxWidth, maxHeight);
        loaded = true;
        error = false;
      } catch (Exception e) {
        error = true;
        e.printStackTrace();
      }
    }
    if (userPause) {
      return;
    }
    if (repeat || frameNum < images.size()) {
      startPlaying();
    }
    try {
      if (images.size() > 1) {
        while (maxWidth > 0 && maxHeight > 0 && engine == me) {
          if (frameNum >= images.size()) {
            if (!repeat) {
              return;
            }
            setFrameNum(0);
          }
          repaint();
          if (sounds != null) {
            AudioClip clip = (AudioClip) sounds.get(frameNumKey);
            if (clip != null) {
              clip.play();
            }
          }
          try {
            Integer pause = null;
            if (durations != null) {
              pause = (Integer) durations.get(frameNumKey);
            }
            if (pause == null) {
              Thread.sleep(globalPause);
            } else {
              Thread.sleep(pause.intValue());
            }
          } catch (InterruptedException e) {
            // Should we do anything?
          }
          setFrameNum(frameNum + 1);
        }
      }
    } finally {
      stopPlaying();
    }
  }
  /**
   * No need to clear anything; just paint.
   */
  public void update(Graphics g) {
    paint(g);
  }
  /**
   * Paint the current frame.
   */
  public void paint(Graphics g) {
    if (error || !loaded) {
      if (startUpImage != null) {
        if (tracker.checkID(STARTUP_ID)) {
          g.drawImage(startUpImage, 0, 0, this);
        }
      } else {
        if (backgroundImage != null) {
          if (tracker.checkID(BACKGROUND_ID)) {
            g.drawImage(backgroundImage, 0, 0, this);
          }
        } else {
          g.clearRect(0, 0, maxWidth, maxHeight);
        }
      }
    } else {
      if ((images != null) && (images.size() > 0)) {
        if (frameNum < images.size()) {
          if (backgroundImage == null) {
            offScrGC.fillRect(0, 0, maxWidth, maxHeight);
          } else {
            offScrGC.drawImage(backgroundImage, 0, 0, this);
          }
          Image image = (Image) images.elementAt(frameNum);
          Point pos = null;
          if (positions != null) {
            pos = (Point) positions.get(frameNumKey);
          }
          if (pos != null) {
            xPos = pos.x;
            yPos = pos.y;
          }
          offScrGC.drawImage(image, xPos, yPos, this);
          g.drawImage(offScrImage, 0, 0, this);
        } else {
          // no more animation, but need to draw something
          dbg("No more animation; drawing last image.");
          if (backgroundImage == null) {
            g.fillRect(0, 0, maxWidth, maxHeight);
          } else {
            g.drawImage(backgroundImage, 0, 0, this);
          }
          g.drawImage((Image) images.lastElement(), 0, 0, this);
        }
      }
    }
  }
  /**
   * Start the applet by forking an animation thread.
   */
  public void start() {
    if (engine == null) {
      engine = new Thread(this);
      engine.start();
    }
  }
  /**
   * Stop the insanity, um, applet.
   */
  public void stop() {
    if (engine != null && engine.isAlive()) {
      engine.stop();
    }
    engine = null;
  }
  /**
   * Pause the thread when the user clicks the mouse in the applet. If the
   * thread has stopped (as in a non-repeat performance), restart it.
   */
  public boolean handleEvent(Event evt) {
    if (evt.id == Event.MOUSE_DOWN) {
      if (loaded) {
        if (engine != null && engine.isAlive()) {
          if (userPause) {
            engine.resume();
            startPlaying();
          } else {
            engine.suspend();
            stopPlaying();
          }
          userPause = !userPause;
        } else {
          userPause = false;
          setFrameNum(0);
          engine = new Thread(this);
          engine.start();
        }
      }
      return true;
    } else {
      return super.handleEvent(evt);
    }
  }
}
class ParseException extends Exception {
  ParseException(String s) {
    super(s);
  }
}
class ImageNotFoundException extends Exception {
  ImageNotFoundException(ImageProducer source) {
    super(source + "");
  }
}



A rotating and scaling rectangle.

    
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class SwingTimerBasedAnimationScaleRotate extends JPanel implements ActionListener {
  Timer timer;
  private double angle = 0;
  private double scale = 1;
  private double delta = 0.01;
  Rectangle.Float r = new Rectangle.Float(20, 20, 200, 200);
  public SwingTimerBasedAnimationScaleRotate() {
    timer = new Timer(10, this);
    timer.start();
  }
  public void paint(Graphics g) {
    int h = getHeight();
    int w = getWidth();
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2d.translate(w / 2, h / 2);
    g2d.rotate(angle);
    g2d.scale(scale, scale);
    g2d.fill(r);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("Moving star");
    frame.add(new SwingTimerBasedAnimationScaleRotate());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(420, 250);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
  public void actionPerformed(ActionEvent e) {
    if (scale < 0.01) {
      delta = -delta;
    } else if (scale > 0.99) {
      delta = -delta;
    }
    scale += delta;
    angle += 0.01;
    repaint();
  }
}



A simple spring simulation in one dimension

  
/*
 *  $Id: FloatSpring.java,v 1.4 2007/06/25 23:00:10 shingoki Exp $
 *
 *  Copyright (c) 2005-2006 shingoki
 *
 *  This file is part of AirCarrier, see http://aircarrier.dev.java.net/
 *
 *    AirCarrier is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *    AirCarrier is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *    You should have received a copy of the GNU General Public License
 *    along with AirCarrier; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
/**
 * A simple spring simulation in one dimension Useful for getting a property
 * (for example a position) to move from one value to another, in a smooth
 * looking way. To use, create a spring with appropriate constants (e.g. new
 * FloatSpring(100) is a reasonable value) Then set spring position to the
 * initial value, and update each frame with target parameter as your desired
 * value. The position parameter will "snap to" the desired value.
 * 
 * @author goki
 */
public class FloatSpring {
  float position;
  float springK;
  float dampingK;
  float velocity;
  /**
   * Make a spring with given spring constant and damping constant
   * 
   * @param springK
   *          Spring constant, the higher this is the "tighter" the spring, and
   *          the more force it will exert for a given extension
   * @param dampingK
   *          Damping constant, the higher this is the stronger the damping, and
   *          the more "soggy" the movement.
   */
  public FloatSpring(float springK, float dampingK) {
    super();
    this.position = 0;
    this.springK = springK;
    this.dampingK = dampingK;
    this.velocity = 0;
  }
  /**
   * Create a critically damped spring (or near to critically damped) This
   * spring will quickly move to its target without overshooting
   * 
   * @param springK
   *          The spring constant - the higher this is, the more quickly the
   *          spring will reach its target. A value of 100 gives a reasonable
   *          response in about a second, a higher value gives a faster
   *          response.
   */
  public FloatSpring(float springK) {
    this(springK, (float) (2 * Math.sqrt(springK)));
  }
  /**
   * Update the position of the spring. This updates the "position" as if there
   * were a damped spring stretched between the current position and the target
   * position. That is, the spring will tend to pull the position towards the
   * target, and if the spring is damped the position will eventually settle
   * onto the target.
   * 
   * @param target
   *          The target towards which the spring is pulling the position
   * @param time
   *          The elapsed time in seconds
   */
  public void update(float target, float time) {
    // Set v to target - position, this is the required movement
    float v = position - target;
    // Multiply displacement by spring constant to get spring force,
    // then subtract damping force
    v = v * -springK - velocity * dampingK;
    // v is now a force, so assuming unit mass is is also acceleration.
    // multiply by elapsed time to get velocity change
    velocity += v * time;
    // If velocity isn"t valid, zero it
    if (Float.isNaN(velocity) || Float.isInfinite(velocity)) {
      velocity = 0;
    }
    // Change the position at the new velocity, for elapsed time
    position += velocity * time;
  }
  /**
   * @return Damping constant, the higher this is the stronger the damping, and
   *         the more "soggy" the movement.
   */
  public float getDampingK() {
    return dampingK;
  }
  /**
   * @param dampingK
   *          Damping constant, the higher this is the stronger the damping, and
   *          the more "soggy" the movement.
   */
  public void setDampingK(float dampingK) {
    this.dampingK = dampingK;
  }
  /**
   * @return The current position of the simulated spring end point, changes as
   *         simulation is updated
   */
  public float getPosition() {
    return position;
  }
  /**
   * @param position
   *          A new position for simulated spring end point
   */
  public void setPosition(float position) {
    this.position = position;
  }
  /**
   * @return The spring constant - the higher this is, the more quickly the
   *         spring will reach its target
   */
  public float getSpringK() {
    return springK;
  }
  /**
   * @param springK
   *          The spring constant - the higher this is, the more quickly the
   *          spring will reach its target
   */
  public void setSpringK(float springK) {
    this.springK = springK;
  }
  /**
   * @return The current velocity of the position
   */
  public float getVelocity() {
    return velocity;
  }
  /**
   * @param velocity
   *          A new value for the current velocity of the position
   */
  public void setVelocity(float velocity) {
    this.velocity = velocity;
  }
}



Bouncing Circle

    
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.ru/javaexamples2.
 */
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
/** An applet that displays a simple animation */
public class BouncingCircle extends Applet implements Runnable {
  int x = 150, y = 50, r = 50; // Position and radius of the circle
  int dx = 11, dy = 7; // Trajectory of circle
  Thread animator; // The thread that performs the animation
  volatile boolean pleaseStop; // A flag to ask the thread to stop
  /** This method simply draws the circle at its current position */
  public void paint(Graphics g) {
    g.setColor(Color.red);
    g.fillOval(x - r, y - r, r * 2, r * 2);
  }
  /**
   * This method moves (and bounces) the circle and then requests a redraw.
   * The animator thread calls this method periodically.
   */
  public void animate() {
    // Bounce if we"ve hit an edge.
    Rectangle bounds = getBounds();
    if ((x - r + dx < 0) || (x + r + dx > bounds.width))
      dx = -dx;
    if ((y - r + dy < 0) || (y + r + dy > bounds.height))
      dy = -dy;
    // Move the circle.
    x += dx;
    y += dy;
    // Ask the browser to call our paint() method to draw the circle
    // at its new position.
    repaint();
  }
  /**
   * This method is from the Runnable interface. It is the body of the thread
   * that performs the animation. The thread itself is created and started in
   * the start() method.
   */
  public void run() {
    while (!pleaseStop) { // Loop until we"re asked to stop
      animate(); // Update and request redraw
      try {
        Thread.sleep(100);
      } // Wait 100 milliseconds
      catch (InterruptedException e) {
      } // Ignore interruptions
    }
  }
  /** Start animating when the browser starts the applet */
  public void start() {
    animator = new Thread(this); // Create a thread
    pleaseStop = false; // Don"t ask it to stop now
    animator.start(); // Start the thread.
    // The thread that called start now returns to its caller.
    // Meanwhile, the new animator thread has called the run() method
  }
  /** Stop animating when the browser stops the applet */
  public void stop() {
    // Set the flag that causes the run() method to end
    pleaseStop = true;
  }
}



Buffered Animation Demo

    
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class BufferedAnimate extends JFrame {
  private static int DELAY = 100;
  Image buffer;
  Dimension oldSize;
  Insets insets;
  Color colors[] = { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN,
      Color.BLUE, Color.MAGENTA };
  public void paint(Graphics g) {
    if ((oldSize == null) || (oldSize != getSize())) {
      oldSize = getSize();
      buffer = new BufferedImage(getWidth(), getHeight(),
          BufferedImage.TYPE_INT_RGB);
    }
    if (insets == null) {
      insets = getInsets();
    }
    // Calculate each time in case of resize
    int x = insets.left;
    int y = insets.top;
    int width = getWidth() - insets.left - insets.right;
    int height = getHeight() - insets.top - insets.bottom;
    int start = 0;
    int steps = colors.length;
    int stepSize = 360 / steps;
    synchronized (colors) {
      Graphics bufferG = buffer.getGraphics();
      bufferG.setColor(Color.WHITE);
      bufferG.fillRect(x, y, width, height);
      for (int i = 0; i < steps; i++) {
        bufferG.setColor(colors[i]);
        bufferG.fillArc(x, y, width, height, start, stepSize);
        start += stepSize;
      }
    }
    g.drawImage(buffer, 0, 0, this);
  }
  public void go() {
    TimerTask task = new TimerTask() {
      public void run() {
        Color c = colors[0];
        synchronized (colors) {
          System.arraycopy(colors, 1, colors, 0, colors.length - 1);
          colors[colors.length - 1] = c;
        }
        repaint();
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0, DELAY);
  }
  public static void main(String args[]) {
    BufferedAnimate f = new BufferedAnimate();
    f.setSize(200, 200);
    f.setTitle("Buffered");
    f.show();
    f.go();
  }
}



Composition technique in this animation.

    
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageComposite extends JPanel implements ActionListener {
  Image a = new ImageIcon(this.getClass().getResource("a.png")).getImage();
  Image b = new ImageIcon(this.getClass().getResource("b.png")).getImage();
  Timer timer = new Timer(800, this);
  float alpha = 1f;
  public ImageComposite() {
    timer.start();
  }
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    BufferedImage buffImg = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB);
    Graphics2D gbi = buffImg.createGraphics();
    AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
    gbi.drawImage(a, 40, 30, null);
    gbi.setComposite(ac);
    gbi.drawImage(b, 0, 0, null);
    g2d.drawImage(buffImg, 20, 20, null);
  }
  public void actionPerformed(ActionEvent e) {
    alpha -= 0.1;
    if (alpha <= 0) {
      alpha = 0;
      timer.stop();
    }
    repaint();
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new ImageComposite());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 210);
    frame.setVisible(true);
  }
}



Fade out an image: image gradually get more transparent until it is completely invisible.

    

import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FadeOutImage extends JPanel implements ActionListener {
  Image myImage = new ImageIcon("a.jpg").getImage();
  Timer timer = new Timer(20, this);
  private float alpha = 1f;
  public FadeOutImage() {
    timer.start();
  }
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
    g2d.drawImage(myImage, 10, 10, null);
  }
  public void actionPerformed(ActionEvent e) {
    alpha += -0.01f;
    if (alpha <= 0) {
      alpha = 0;
      timer.stop();
    }
    repaint();
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("Fade out");
    frame.add(new FadeOutImage());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 250);
    frame.setVisible(true);
  }
}



Font size animation

    
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FontSizeAnimation extends JPanel implements ActionListener {
  Timer timer;
  int x = 1;
  float alpha = 1;
  public FontSizeAnimation() {
    timer = new Timer(8, this);
    timer.setInitialDelay(190);
    timer.start();
  }
  public void paint(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    Font font = new Font("Dialog", Font.PLAIN, x);
    g2d.setFont(font);
    FontMetrics fm = g2d.getFontMetrics();
    String s = "Java";
    
    int w = (int) getSize().getWidth();
    int h = (int) getSize().getHeight();
    int stringWidth = fm.stringWidth(s);
    g2d.drawString(s, (w - stringWidth) / 2, h / 2);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("FontSizeAnimation");
    frame.add(new FontSizeAnimation());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
  public void actionPerformed(ActionEvent e) {
    x += 1;
    alpha -= 0.0001;
    repaint();
  }
}



How to create animation

    
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class AppletAnimation extends Applet implements Runnable {
  int frameNumber = -1;
  int delay = 100;
  Thread animatorThread;
  boolean frozen = false;
  public void init() {
    String str;
    addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        if (frozen) {
          frozen = false;
          start();
        } else {
          frozen = true;
          stop();
        }
      }
    });
  }
  public void start() {
    if (!frozen) {
      if (animatorThread == null) {
        animatorThread = new Thread(this);
      }
      animatorThread.start();
    }
  }
  public void stop() {
    animatorThread = null;
  }
  public void run() {
    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    long startTime = System.currentTimeMillis();
    Thread currentThread = Thread.currentThread();
    while (currentThread == animatorThread) {
      frameNumber++;
      repaint();
      try {
        startTime += delay;
        Thread.sleep(100);
      } catch (InterruptedException e) {
        break;
      }
    }
  }
  public void paint(Graphics g) {
    g.drawString("Frame " + frameNumber, 0, 30);
  }
}



How to create Animation: Paint and thread

    
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class Animate extends JFrame {
  private static int DELAY = 100;
  Insets insets;
  Color colors[] = { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN,
      Color.BLUE, Color.MAGENTA };
  public void paint(Graphics g) {
    super.paint(g);
    if (insets == null) {
      insets = getInsets();
    }
    // Calculate each time in case of resize
    int x = insets.left;
    int y = insets.top;
    int width = getWidth() - insets.left - insets.right;
    int height = getHeight() - insets.top - insets.bottom;
    int start = 0;
    int steps = colors.length;
    int stepSize = 360 / steps;
    synchronized (colors) {
      for (int i = 0; i < steps; i++) {
        g.setColor(colors[i]);
        g.fillArc(x, y, width, height, start, stepSize);
        start += stepSize;
      }
    }
  }
  public void go() {
    TimerTask task = new TimerTask() {
      public void run() {
        Color c = colors[0];
        synchronized (colors) {
          System.arraycopy(colors, 1, colors, 0, colors.length - 1);
          colors[colors.length - 1] = c;
        }
        repaint();
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0, DELAY);
  }
  public static void main(String args[]) {
    Animate f = new Animate();
    f.setSize(200, 200);
    f.show();
    f.go();
  }
}



Hypnosis animation

    
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Hypnosis1 extends JComponent implements Runnable {
  private int[] coordinates;
  private int[] deltas;
  private Paint paint;
  public Hypnosis1(int numberOfSegments) {
    int numberOfCoordinates = numberOfSegments * 4 + 2;
    coordinates = new int[numberOfCoordinates];
    deltas = new int[numberOfCoordinates];
    for (int i = 0; i < numberOfCoordinates; i++) {
      coordinates[i] = (int) (Math.random() * 300);
      deltas[i] = (int) (Math.random() * 4 + 3);
      if (deltas[i] > 4)
        deltas[i] = -(deltas[i] - 3);
    }
    paint = new GradientPaint(0, 0, Color.blue, 20, 10, Color.red, true);
    Thread t = new Thread(this);
    t.start();
  }
  public void run() {
    try {
      while (true) {
        timeStep();
        repaint();
        Thread.sleep(1000 / 24);
      }
    } catch (InterruptedException ie) {
    }
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Shape s = createShape();
    g2.setPaint(paint);
    g2.fill(s);
    g2.setPaint(Color.white);
    g2.draw(s);
  }
  private void timeStep() {
    Dimension d = getSize();
    if (d.width == 0 || d.height == 0)
      return;
    for (int i = 0; i < coordinates.length; i++) {
      coordinates[i] += deltas[i];
      int limit = (i % 2 == 0) ? d.width : d.height;
      if (coordinates[i] < 0) {
        coordinates[i] = 0;
        deltas[i] = -deltas[i];
      } else if (coordinates[i] > limit) {
        coordinates[i] = limit - 1;
        deltas[i] = -deltas[i];
      }
    }
  }
  private Shape createShape() {
    GeneralPath path = new GeneralPath();
    path.moveTo(coordinates[0], coordinates[1]);
    for (int i = 2; i < coordinates.length; i += 4)
      path.quadTo(coordinates[i], coordinates[i + 1], coordinates[i + 2], coordinates[i + 3]);
    path.closePath();
    return path;
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("Hypnosis");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(new Hypnosis1(4));
    f.setSize(300, 300);
    f.setVisible(true);
  }
}



Image Bouncer

    
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ruponentAdapter;
import java.awt.event.ruponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageBouncer extends JPanel implements Runnable {
  private boolean trucking = true;
  private long[] previousTimes; // milliseconds
  private int previousIndex;
  private boolean previousFilled;
  private double frameRate; // frames per second
  public static void main(String[] args) {
    String filename = "jexpLogo.png";
    if (args.length > 0)
      filename = args[0];
    Image image = null;
    try {
      image = blockingLoad(new URL(filename));
    } catch (MalformedURLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    final ImageBouncer bouncer = new ImageBouncer(image);
    Frame f = new AnimationFrame(bouncer);
    f.setFont(new Font("Serif", Font.PLAIN, 12));
    Panel controls = new Panel();
    controls.add(bouncer.createCheckbox("Bilinear", ImageBouncer.BILINEAR));
    controls.add(bouncer.createCheckbox("Transform", ImageBouncer.TRANSFORM));
    final Choice typeChoice = new Choice();
    typeChoice.add("TYPE_INT_RGB");
    typeChoice.add("TYPE_INT_ARGB");
    typeChoice.add("TYPE_INT_ARGB_PRE");
    typeChoice.add("TYPE_3BYTE_BGR");
    typeChoice.add("TYPE_BYTE_GRAY");
    typeChoice.add("TYPE_USHORT_GRAY");
    typeChoice.add("TYPE_USHORT_555_RGB");
    typeChoice.add("TYPE_USHORT_565_RGB");
    controls.add(typeChoice);
    f.add(controls, BorderLayout.NORTH);
    typeChoice.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        String type = typeChoice.getSelectedItem();
        bouncer.setImageType(type);
      }
    });
f.setSize(200,200);
    f.setVisible(true);
  }
  private boolean mBilinear = false;
  private boolean mTransform = false;
  public static final int BILINEAR = 1;
  public static final int TRANSFORM = 3;
  private float mDeltaX, mDeltaY;
  private float mX, mY, mWidth, mHeight;
  private float mTheta;
  private Image mOriginalImage;
  private Image image;
  public ImageBouncer(Image image) {
    previousTimes = new long[128];
    previousTimes[0] = System.currentTimeMillis();
    previousIndex = 1;
    previousFilled = false;
  
    mOriginalImage = image;
    setImageType("TYPE_INT_RGB");
    Random random = new Random();
    mX = random.nextFloat() * 500;
    mY = random.nextFloat() * 500;
    mWidth = image.getWidth(this);
    mHeight = image.getHeight(this);
    mDeltaX = random.nextFloat() * 3;
    mDeltaY = random.nextFloat() * 3;
    // Make sure points are within range.
    addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent ce) {
        Dimension d = getSize();
        if (mX < 0)
          mX = 0;
        else if (mX + mWidth >= d.width)
          mX = d.width - mWidth - 1;
        if (mY < 0)
          mY = 0;
        else if (mY + mHeight >= d.height)
          mY = d.height - mHeight - 1;
      }
    });
  }
  public void setSwitch(int item, boolean value) {
    switch (item) {
    case BILINEAR:
      mBilinear = value;
      break;
    case TRANSFORM:
      mTransform = value;
      break;
    default:
      break;
    }
  }
  public void setImageType(String s) {
    int type = BufferedImage.TYPE_CUSTOM;
    if (s.equals("TYPE_INT_RGB"))
      type = BufferedImage.TYPE_INT_RGB;
    else if (s.equals("TYPE_INT_ARGB"))
      type = BufferedImage.TYPE_INT_ARGB;
    else if (s.equals("TYPE_INT_ARGB_PRE"))
      type = BufferedImage.TYPE_INT_ARGB_PRE;
    else if (s.equals("TYPE_3BYTE_BGR"))
      type = BufferedImage.TYPE_3BYTE_BGR;
    else if (s.equals("TYPE_BYTE_GRAY"))
      type = BufferedImage.TYPE_BYTE_GRAY;
    else if (s.equals("TYPE_USHORT_GRAY"))
      type = BufferedImage.TYPE_USHORT_GRAY;
    else if (s.equals("TYPE_USHORT_555_RGB"))
      type = BufferedImage.TYPE_USHORT_565_RGB;
    else if (s.equals("TYPE_USHORT_565_RGB"))
      type = BufferedImage.TYPE_USHORT_565_RGB;
    else {
      System.out.println("Unrecognized type.");
      return;
    }
    image = makeBufferedImage(mOriginalImage, type);
  }
  protected Checkbox createCheckbox(String label, final int item) {
    Checkbox check = new Checkbox(label);
    check.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        setSwitch(item, (ie.getStateChange() == ie.SELECTED));
      }
    });
    return check;
  }
  public void timeStep() {
    Dimension d = getSize();
    if (mX + mDeltaX < 0)
      mDeltaX = -mDeltaX;
    else if (mX + mWidth + mDeltaX >= d.width)
      mDeltaX = -mDeltaX;
    if (mY + mDeltaY < 0)
      mDeltaY = -mDeltaY;
    else if (mY + mHeight + mDeltaY >= d.height)
      mDeltaY = -mDeltaY;
    mX += mDeltaX;
    mY += mDeltaY;
    mTheta += Math.PI / 192;
    if (mTheta > (2 * Math.PI))
      mTheta -= (2 * Math.PI);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    setTransform(g2);
    setBilinear(g2);
    // Draw the image.
    g2
        .drawImage(image,
            AffineTransform.getTranslateInstance(mX, mY), null);
  }
  protected void setTransform(Graphics2D g2) {
    if (mTransform == false)
      return;
    float cx = mX + mWidth / 2;
    float cy = mY + mHeight / 2;
    g2.rotate(mTheta, cx, cy);
  }
  protected void setBilinear(Graphics2D g2) {
    if (mBilinear == false)
      return;
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  }
  public void run() {
    while (trucking) {
      render();
      timeStep();
      calculateFrameRate();
    }
  }
  protected void render() {
    Graphics g = getGraphics();
    if (g != null) {
      Dimension d = getSize();
      if (checkImage(d)) {
        Graphics imageGraphics = image.getGraphics();
        // Clear the image background.
        imageGraphics.setColor(getBackground());
        imageGraphics.fillRect(0, 0, d.width, d.height);
        imageGraphics.setColor(getForeground());
        // Draw this component offscreen.
        paint(imageGraphics);
        // Now put the offscreen image on the screen.
        g.drawImage(image, 0, 0, null);
        // Clean up.
        imageGraphics.dispose();
      }
      g.dispose();
    }
  }
  // Offscreen image.
  protected boolean checkImage(Dimension d) {
    if (d.width == 0 || d.height == 0)
      return false;
    if (image == null || image.getWidth(null) != d.width
        || image.getHeight(null) != d.height) {
      image = createImage(d.width, d.height);
    }
    return true;
  }
  protected void calculateFrameRate() {
    // Measure the frame rate
    long now = System.currentTimeMillis();
    int numberOfFrames = previousTimes.length;
    double newRate;
    // Use the more stable method if a history is available.
    if (previousFilled)
      newRate = (double) numberOfFrames
          / (double) (now - previousTimes[previousIndex]) * 1000.0;
    else
      newRate = 1000.0 / (double) (now - previousTimes[numberOfFrames - 1]);
    firePropertyChange("frameRate", frameRate, newRate);
    frameRate = newRate;
    // Update the history.
    previousTimes[previousIndex] = now;
    previousIndex++;
    if (previousIndex >= numberOfFrames) {
      previousIndex = 0;
      previousFilled = true;
    }
  }
  public double getFrameRate() {
    return frameRate;
  }
  // Property change support.
  private transient AnimationFrame mRateListener;
  public void setRateListener(AnimationFrame af) {
    mRateListener = af;
  }
  public void firePropertyChange(String name, double oldValue, double newValue) {
    mRateListener.rateChanged(newValue);
  }
  private static Component sComponent = new Component() {
  };
  private static final MediaTracker sTracker = new MediaTracker(sComponent);
  private static int sID = 0;
  public static boolean waitForImage(Image image) {
    int id;
    synchronized (sComponent) {
      id = sID++;
    }
    sTracker.addImage(image, id);
    try {
      sTracker.waitForID(id);
    } catch (InterruptedException ie) {
      return false;
    }
    if (sTracker.isErrorID(id))
      return false;
    return true;
  }
  public Image blockingLoad(String path) {
    Image image = Toolkit.getDefaultToolkit().getImage(path);
    if (waitForImage(image) == false)
      return null;
    return image;
  }
  public static Image blockingLoad(URL url) {
    Image image = Toolkit.getDefaultToolkit().getImage(url);
    if (waitForImage(image) == false)
      return null;
    return image;
  }
  public BufferedImage makeBufferedImage(Image image) {
    return makeBufferedImage(image, BufferedImage.TYPE_INT_RGB);
  }
  public BufferedImage makeBufferedImage(Image image, int imageType) {
    if (waitForImage(image) == false)
      return null;
    BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
        image.getHeight(null), imageType);
    Graphics2D g2 = bufferedImage.createGraphics();
    g2.drawImage(image, null, null);
    return bufferedImage;
  }
}
class AnimationFrame extends JFrame {
  private Label mStatusLabel;
  private NumberFormat mFormat;
  public AnimationFrame(ImageBouncer ac) {
    super();
    setLayout(new BorderLayout());
    add(ac, BorderLayout.CENTER);
    add(mStatusLabel = new Label(), BorderLayout.SOUTH);
    // Create a number formatter.
    mFormat = NumberFormat.getInstance();
    mFormat.setMaximumFractionDigits(1);
    // Listen for the frame rate changes.
    ac.setRateListener(this);
    // Kick off the animation.
    Thread t = new Thread(ac);
    t.start();
  }
  public void rateChanged(double frameRate) {
    mStatusLabel.setText(mFormat.format(frameRate) + " fps");
  }
}



Is Event Dispatcher Thread

    
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
public class IsEDTExample extends JPanel {
  private boolean keepRunning;
  private static int RED = 0;
  private static int BLUE = 1;
  private static int GREEN = 2;
  private static int VARIABLE = 3;
  private static int SIZE = 3;
  private int threadShade;
  private ColorTableModel tableModel= new ColorTableModel();
  private Thread colorShadeThread;
  public IsEDTExample() {
    JTable table = new JTable(tableModel);
    table.setRowHeight(100);
    table.setDefaultRenderer(Object.class, new ColorRenderer());
    add(table);
    add(new JLabel("Thread Color Shade:"));
    ButtonGroup group = new ButtonGroup();
    JRadioButton redOption = new JRadioButton("Red");
    group.add(redOption);
    redOption.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        threadShade = RED;
      }
    });
    JRadioButton blueOption = new JRadioButton("Blue");
    group.add(blueOption);
    blueOption.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        threadShade = BLUE;
      }
    });
    JRadioButton greenOption = new JRadioButton("Green");
    group.add(greenOption);
    greenOption.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        threadShade = GREEN;
      }
    });
    redOption.setSelected(true);
    this.threadShade = RED;
    add(redOption);
    add(greenOption);
    add(blueOption);
    add(new JButton(new RandomColorAction()));
    this.keepRunning = true;
    this.colorShadeThread = new Thread(new RandomColorShadeRunnable());
    this.colorShadeThread.start();
  }
  private class RandomColorAction extends AbstractAction {
    public RandomColorAction() {
      super("Create Random Color");
    }
    public void actionPerformed(ActionEvent e) {
      IsEDTExample.this.tableModel.generateRandomColor(VARIABLE);
    }
  }
  private class ColorTableModel extends AbstractTableModel {
    private Color[][] colors = new Color[3][3];
    public ColorTableModel() {
      for (int i = 0; i < SIZE; i++) {
        for (int x = 0; x < SIZE; x++) {
          colors[i][x] = Color.white;
        }
      }
    }
    public int getRowCount() {
      return SIZE;
    }
    public int getColumnCount() {
      return SIZE;
    }
    public Object getValueAt(int rowIndex, int columnIndex) {
      return colors[rowIndex][columnIndex];
    }
    public void generateRandomColor(int type) {
      Random random = new Random(System.currentTimeMillis());
      final int row = random.nextInt(SIZE);
      final int column = random.nextInt(SIZE);
      final Color color;
      if (type == RED) {
        color = new Color(random.nextInt(256), 0, 0);
      } else if (type == BLUE) {
        color = new Color(0, 0, random.nextInt(256));
      } else if (type == GREEN) {
        color = new Color(0, random.nextInt(256), 0);
      } else {
        color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
      }
      if (SwingUtilities.isEventDispatchThread()) {
        colors[row][column] = color;
        fireTableCellUpdated(row, column);
      } else {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            colors[row][column] = color;
            fireTableCellUpdated(row, column);
          }
        });
      }
    }
  }
  private class ColorRenderer implements TableCellRenderer {
    private JLabel label;
    public ColorRenderer() {
      label = new JLabel();
      label.setOpaque(true);
      label.setPreferredSize(new Dimension(100, 100));
    }
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
      label.setBackground((Color) value);
      return label;
    }
  }
  private class RandomColorShadeRunnable implements Runnable {
    public void run() {
      while (keepRunning) {
        tableModel.generateRandomColor(threadShade);
        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
        }
      }
    }
  }
  public static void main(String[] a) {
    JFrame f = new JFrame("Is Event Dispatch Thread Example");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(new IsEDTExample());
    f.pack();
    f.setVisible(true);
  }
}



Make your own animation from a series of images

    
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main extends JPanel implements ActionListener {
  ImageIcon images[];
  int totalImages = 30, currentImage = 0, animationDelay = 50;
  Timer animationTimer;
  public Main() {
    images = new ImageIcon[totalImages];
    for (int i = 0; i < images.length; ++i)
      images[i] = new ImageIcon("images/java" + i + ".gif");
    startAnimation();
  }
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (images[currentImage].getImageLoadStatus() == MediaTracker.ruPLETE) {
      images[currentImage].paintIcon(this, g, 0, 0);
      currentImage = (currentImage + 1) % totalImages;
    }
  }
  public void actionPerformed(ActionEvent e) {
    repaint();
  }
  public void startAnimation() {
    if (animationTimer == null) {
      currentImage = 0;
      animationTimer = new Timer(animationDelay, this);
      animationTimer.start();
    } else if (!animationTimer.isRunning())
      animationTimer.restart();
  }
  public void stopAnimation() {
    animationTimer.stop();
  }
  public static void main(String args[]) {
    Main anim = new Main();
    JFrame app = new JFrame("Animator test");
    app.add(anim, BorderLayout.CENTER);
    app.setSize(300,300);
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.setSize(anim.getPreferredSize().width + 10, anim.getPreferredSize().height + 30);
  }
}



Noise Image

    
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class StaticGenerator extends JComponent implements Runnable {
  byte[] data;
  BufferedImage image;
  Random random;
  public void initialize() {
    int w = getSize().width, h = getSize().height;
    int length = ((w + 7) * h) / 8;
    data = new byte[length];
    DataBuffer db = new DataBufferByte(data, length);
    WritableRaster wr = Raster.createPackedRaster(db, w, h, 1, null);
    ColorModel cm = new IndexColorModel(1, 2, new byte[] { (byte) 0, (byte) 255 }, new byte[] {
        (byte) 0, (byte) 255 }, new byte[] { (byte) 0, (byte) 255 });
    image = new BufferedImage(cm, wr, false, null);
    random = new Random();
    new Thread(this).start();
  }
  public void run() {
    while (true) {
      random.nextBytes(data);
      repaint();
      try {
        Thread.sleep(1000 / 24);
      } catch (InterruptedException e) { /* die */
      }
    }
  }
  public void paint(Graphics g) {
    if (image == null)
      initialize();
    g.drawImage(image, 0, 0, this);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.add(new StaticGenerator());
    f.setSize(300, 300);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}



Text animation

    
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ruponentAdapter;
import java.awt.event.ruponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TextBouncer extends JPanel implements Runnable {
  private boolean trucking = true;
  private long[] previousTimes; // milliseconds
  private int previousIndex;
  private boolean previousFilled;
  private double frameRate; // frames per second
  private Image image = null;
  public static void main(String[] args) {
    
    String s = "Java Source and Support";
    final int size = 64;
    if (args.length > 0)
      s = args[0];
    Panel controls = new Panel();
    final Choice choice = new Choice();
    GraphicsEnvironment ge = GraphicsEnvironment
        .getLocalGraphicsEnvironment();
    Font[] allFonts = ge.getAllFonts();
    for (int i = 0; i < allFonts.length; i++)
      choice.addItem(allFonts[i].getName());
    Font defaultFont = new Font(allFonts[0].getName(), Font.PLAIN, size);
    final TextBouncer bouncer = new TextBouncer(s, defaultFont);
    Frame f = new AnimationFrame(bouncer);
    f.setFont(new Font("Serif", Font.PLAIN, 12));
    controls.add(bouncer.createCheckbox("Antialiasing",
        TextBouncer.ANTIALIASING));
    controls.add(bouncer.createCheckbox("Gradient", TextBouncer.GRADIENT));
    controls.add(bouncer.createCheckbox("Shear", TextBouncer.SHEAR));
    controls.add(bouncer.createCheckbox("Rotate", TextBouncer.ROTATE));
    controls.add(bouncer.createCheckbox("Axes", TextBouncer.AXES));
    Panel fontControls = new Panel();
    choice.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        Font font = new Font(choice.getSelectedItem(), Font.PLAIN, size);
        bouncer.setFont(font);
      }
    });
    fontControls.add(choice);
    Panel allControls = new Panel(new GridLayout(2, 1));
    allControls.add(controls);
    allControls.add(fontControls);
    f.add(allControls, BorderLayout.NORTH);
        f.setSize(300,300);
    f.setVisible(true);
  }
  private boolean mAntialiasing = false, mGradient = false;
  private boolean mShear = false, mRotate = false, mAxes = false;
  public static final int ANTIALIASING = 0;
  public static final int GRADIENT = 1;
  public static final int SHEAR = 2;
  public static final int ROTATE = 3;
  public static final int AXES = 5;
  private float mDeltaX, mDeltaY;
  private float mX, mY, mWidth, mHeight;
  private float mTheta;
  private float mShearX, mShearY, mShearDeltaX, mShearDeltaY;
  private String mString;
  public TextBouncer(String s, Font f) {
    previousTimes = new long[128];
    previousTimes[0] = System.currentTimeMillis();
    previousIndex = 1;
    previousFilled = false;
    
    mString = s;
    setFont(f);
    Random random = new Random();
    mX = random.nextFloat() * 500;
    mY = random.nextFloat() * 500;
    mDeltaX = random.nextFloat() * 3;
    mDeltaY = random.nextFloat() * 3;
    mShearX = random.nextFloat() / 2;
    mShearY = random.nextFloat() / 2;
    mShearDeltaX = mShearDeltaY = .05f;
    FontRenderContext frc = new FontRenderContext(null, true, false);
    Rectangle2D bounds = getFont().getStringBounds(mString, frc);
    mWidth = (float) bounds.getWidth();
    mHeight = (float) bounds.getHeight();
    // Make sure points are within range.
    addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent ce) {
        Dimension d = getSize();
        if (mX < 0)
          mX = 0;
        else if (mX + mWidth >= d.width)
          mX = d.width - mWidth - 1;
        if (mY < 0)
          mY = 0;
        else if (mY + mHeight >= d.height)
          mY = d.height - mHeight - 1;
      }
    });
  }
  public void setSwitch(int item, boolean value) {
    switch (item) {
    case ANTIALIASING:
      mAntialiasing = value;
      break;
    case GRADIENT:
      mGradient = value;
      break;
    case SHEAR:
      mShear = value;
      break;
    case ROTATE:
      mRotate = value;
      break;
    case AXES:
      mAxes = value;
      break;
    default:
      break;
    }
  }
  protected Checkbox createCheckbox(String label, final int item) {
    Checkbox check = new Checkbox(label);
    check.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        setSwitch(item, (ie.getStateChange() == ie.SELECTED));
      }
    });
    return check;
  }
  public void timeStep() {
    Dimension d = getSize();
    if (mX + mDeltaX < 0)
      mDeltaX = -mDeltaX;
    else if (mX + mWidth + mDeltaX >= d.width)
      mDeltaX = -mDeltaX;
    if (mY + mDeltaY < 0)
      mDeltaY = -mDeltaY;
    else if (mY + mHeight + mDeltaY >= d.height)
      mDeltaY = -mDeltaY;
    mX += mDeltaX;
    mY += mDeltaY;
    mTheta += Math.PI / 192;
    if (mTheta > (2 * Math.PI))
      mTheta -= (2 * Math.PI);
    if (mShearX + mShearDeltaX > .5)
      mShearDeltaX = -mShearDeltaX;
    else if (mShearX + mShearDeltaX < -.5)
      mShearDeltaX = -mShearDeltaX;
    if (mShearY + mShearDeltaY > .5)
      mShearDeltaY = -mShearDeltaY;
    else if (mShearY + mShearDeltaY < -.5)
      mShearDeltaY = -mShearDeltaY;
    mShearX += mShearDeltaX;
    mShearY += mShearDeltaY;
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    setAntialiasing(g2);
    setTransform(g2);
    setPaint(g2);
    // Draw the string.
    g2.setFont(getFont());
    g2.drawString(mString, mX, mY + mHeight);
    drawAxes(g2);
  }
  protected void setAntialiasing(Graphics2D g2) {
    if (mAntialiasing == false)
      return;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
  }
  protected void setTransform(Graphics2D g2) {
    Dimension d = getSize();
    int cx = d.width / 2;
    int cy = d.height / 2;
    g2.translate(cx, cy);
    if (mShear)
      g2.shear(mShearX, mShearY);
    if (mRotate)
      g2.rotate(mTheta);
    g2.translate(-cx, -cy);
  }
  protected void setPaint(Graphics2D g2) {
    if (mGradient) {
      GradientPaint gp = new GradientPaint(0, 0, Color.blue, 50, 25,
          Color.green, true);
      g2.setPaint(gp);
    } else
      g2.setPaint(Color.orange);
  }
  protected void drawAxes(Graphics2D g2) {
    if (mAxes == false)
      return;
    g2.setPaint(getForeground());
    g2.setStroke(new BasicStroke());
    Dimension d = getSize();
    int side = 20;
    int arrow = 4;
    int w = d.width / 2, h = d.height / 2;
    g2.drawLine(w - side, h, w + side, h);
    g2.drawLine(w + side - arrow, h - arrow, w + side, h);
    g2.drawLine(w, h - side, w, h + side);
    g2.drawLine(w + arrow, h + side - arrow, w, h + side);
  }
  public void run() {
    while (trucking) {
      render();
      timeStep();
      calculateFrameRate();
    }
  }
  protected void render() {
    Graphics g = getGraphics();
    if (g != null) {
      Dimension d = getSize();
      if (checkImage(d)) {
        Graphics imageGraphics = image.getGraphics();
        // Clear the image background.
        imageGraphics.setColor(getBackground());
        imageGraphics.fillRect(0, 0, d.width, d.height);
        imageGraphics.setColor(getForeground());
        // Draw this component offscreen.
        paint(imageGraphics);
        // Now put the offscreen image on the screen.
        g.drawImage(image, 0, 0, null);
        // Clean up.
        imageGraphics.dispose();
      }
      g.dispose();
    }
  }
  // Offscreen image.
  protected boolean checkImage(Dimension d) {
    if (d.width == 0 || d.height == 0)
      return false;
    if (image == null || image.getWidth(null) != d.width
        || image.getHeight(null) != d.height) {
      image = createImage(d.width, d.height);
    }
    return true;
  }
  protected void calculateFrameRate() {
    // Measure the frame rate
    long now = System.currentTimeMillis();
    int numberOfFrames = previousTimes.length;
    double newRate;
    // Use the more stable method if a history is available.
    if (previousFilled)
      newRate = (double) numberOfFrames
          / (double) (now - previousTimes[previousIndex]) * 1000.0;
    else
      newRate = 1000.0 / (double) (now - previousTimes[numberOfFrames - 1]);
    firePropertyChange("frameRate", frameRate, newRate);
    frameRate = newRate;
    // Update the history.
    previousTimes[previousIndex] = now;
    previousIndex++;
    if (previousIndex >= numberOfFrames) {
      previousIndex = 0;
      previousFilled = true;
    }
  }
  public double getFrameRate() {
    return frameRate;
  }
  // Property change support.
  private transient AnimationFrame mRateListener;
  public void setRateListener(AnimationFrame af) {
    mRateListener = af;
  }
  public void firePropertyChange(String name, double oldValue, double newValue) {
    mRateListener.rateChanged(newValue);
  }
  private static Component sComponent = new Component() {
  };
  private static final MediaTracker sTracker = new MediaTracker(sComponent);
  private static int sID = 0;
  public static boolean waitForImage(Image image) {
    int id;
    synchronized (sComponent) {
      id = sID++;
    }
    sTracker.addImage(image, id);
    try {
      sTracker.waitForID(id);
    } catch (InterruptedException ie) {
      return false;
    }
    if (sTracker.isErrorID(id))
      return false;
    return true;
  }
  public Image blockingLoad(String path) {
    Image image = Toolkit.getDefaultToolkit().getImage(path);
    if (waitForImage(image) == false)
      return null;
    return image;
  }
  public static Image blockingLoad(URL url) {
    Image image = Toolkit.getDefaultToolkit().getImage(url);
    if (waitForImage(image) == false)
      return null;
    return image;
  }
  public BufferedImage makeBufferedImage(Image image) {
    return makeBufferedImage(image, BufferedImage.TYPE_INT_RGB);
  }
  public BufferedImage makeBufferedImage(Image image, int imageType) {
    if (waitForImage(image) == false)
      return null;
    BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
        image.getHeight(null), imageType);
    Graphics2D g2 = bufferedImage.createGraphics();
    g2.drawImage(image, null, null);
    return bufferedImage;
  }
}
class AnimationFrame extends JFrame {
  private Label mStatusLabel;
  private NumberFormat mFormat;
  public AnimationFrame(TextBouncer ac) {
    super();
    setLayout(new BorderLayout());
    add(ac, BorderLayout.CENTER);
    add(mStatusLabel = new Label(), BorderLayout.SOUTH);
    // Create a number formatter.
    mFormat = NumberFormat.getInstance();
    mFormat.setMaximumFractionDigits(1);
    // Listen for the frame rate changes.
    ac.setRateListener(this);
    // Kick off the animation.
    Thread t = new Thread(ac);
    t.start();
  }
  public void rateChanged(double frameRate) {
    mStatusLabel.setText(mFormat.format(frameRate) + " fps");
  }
}



Timer based animation

    
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TimerBasedAnimation extends JPanel implements ActionListener {
  private Ellipse2D.Float ellipse = new Ellipse2D.Float();
  private double esize;
  private double maxSize = 0;
  private boolean initialize = true;
  Timer timer;
  ActionListener updateProBar;
  public TimerBasedAnimation() {
    setXY(20 * Math.random(), 200, 200);
    timer = new Timer(20, this);
    timer.setInitialDelay(190);
    timer.start();
  }
  public void setXY(double size, int w, int h) {
    esize = size;
    ellipse.setFrame(10, 10, size, size);
  }
  public void reset(int w, int h) {
    maxSize = w / 10;
    setXY(maxSize * Math.random(), w, h);
  }
  public void step(int w, int h) {
    esize++;
    if (esize > maxSize) {
      setXY(1, w, h);
    } else {
      ellipse.setFrame(ellipse.getX(), ellipse.getY(), esize, esize);
    }
  }
  public void render(int w, int h, Graphics2D g2) {
    g2.setColor(Color.BLUE);
    g2.draw(ellipse);
  }
  public void paint(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2.setRenderingHints(rh);
    Dimension size = getSize();
    if (initialize) {
      reset(size.width, size.height);
      initialize = false;
    }
    this.step(size.width, size.height);
    render(size.width, size.height, g2);
  }
  public void actionPerformed(ActionEvent e) {
    repaint();
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("TimerBasedAnimation");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new TimerBasedAnimation());
    frame.setSize(350, 250);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}



Towers of Hanoi

<source lang="java"> import java.awt.*; import javax.swing.*; import no.geosoft.cc.graphics.*;

/**

* G demo program. Demonstrates:
*
*
    *
  • A sample game application *
  • Graphics animation *
  • GObject reparenting *
* 
* @author