Java/2D Graphics GUI/Animation — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 06:55, 1 июня 2010
Содержание
- 1 Animated Button
- 2 Animated Message Panel
- 3 Animated PasswordField
- 4 Animated TextField
- 5 Animation: bounce
- 6 Animator Demo
- 7 A rotating and scaling rectangle.
- 8 A simple spring simulation in one dimension
- 9 Bouncing Circle
- 10 Buffered Animation Demo
- 11 Composition technique in this animation.
- 12 Fade out an image: image gradually get more transparent until it is completely invisible.
- 13 Font size animation
- 14 How to create animation
- 15 How to create Animation: Paint and thread
- 16 Hypnosis animation
- 17 Image Bouncer
- 18 Is Event Dispatcher Thread
- 19 Make your own animation from a series of images
- 20 Noise Image
- 21 Text animation
- 22 Timer based animation
- 23 Towers of Hanoi
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