Java/2D Graphics GUI/Animation
Содержание
- 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
<source lang="java"> /**
* 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); } }
}
</source>
Animated Message Panel
<source lang="java"> /**
* 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(); }
}
</source>
Animated PasswordField
<source lang="java"> /**
* 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) { } } }
}
</source>
Animated TextField
<source lang="java"> /**
* 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) { } } }
}
</source>
Animation: bounce
<source lang="java"> 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"); }
}
</source>
Animator Demo
<source lang="java"> /* 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 + ""); }
}
</source>
A rotating and scaling rectangle.
<source lang="java"> 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(); }
}
</source>
A simple spring simulation in one dimension
<source lang="java"> /*
* $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; }
}
</source>
Bouncing Circle
<source lang="java"> /*
* 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; }
}
</source>
Buffered Animation Demo
<source lang="java"> 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(); }
}
</source>
Composition technique in this animation.
<source lang="java"> 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); }
}
</source>
Fade out an image: image gradually get more transparent until it is completely invisible.
<source lang="java">
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); }
}
</source>
Font size animation
<source lang="java"> 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(); }
}
</source>
How to create animation
<source lang="java"> 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); }
}
</source>
How to create Animation: Paint and thread
<source lang="java"> 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(); }
}
</source>
Hypnosis animation
<source lang="java"> 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); }
}
</source>
Image Bouncer
<source lang="java"> 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"); }
}
</source>
Is Event Dispatcher Thread
<source lang="java"> 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); }
}
</source>
Make your own animation from a series of images
<source lang="java"> 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); }
}
</source>
Noise Image
<source lang="java"> 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); }
}
</source>
Text animation
<source lang="java"> 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"); }
}
</source>
Timer based animation
<source lang="java"> 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); }
}
</source>
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