CSE190L Animation Example handout #3
Driver class AnimationMain.java
-------------------------------
// This program launches a frame that shows an animation.
public class AnimationMain {
public static void main(String[] args) {
AnimationFrame f = new AnimationFrame();
f.start();
}
}
Frame class AnimationFrame.java
-------------------------------
// This class creates a frame with a AnimationPanel. It attaches a timer to
// the animation panel that generates an animation by asking the panel to
// repaint itself at regular intervals. The frame also includes a slider that
// allows the user to ask the timer to speed up or slow down the rate at which
// it asks the panel to repaint.
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class AnimationFrame {
private JFrame frame;
private AnimationPanel panel;
private Timer timer;
// post: Constructs all of the objects needed for the animation: the frame,
// the panel, the slider and the timer.
public AnimationFrame() {
// set up frame
frame = new JFrame();
frame.setTitle("Fun with Animation");
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set up animation panel
panel = new AnimationPanel();
frame.add(panel, "Center");
// set up timer and slider
addTimer();
addSlider();
}
// pre : all components have been initialized
// post: begins the animation by making the frame visible and starting
// the timer
public void start() {
frame.setVisible(true);
timer.start();
}
// post: creates a timer that repaints the animation
private void addTimer() {
timer = new Timer(0, new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
});
timer.setCoalesce(true);
}
// post: creates a slider that allows the user to change the speed of the
// animation (frames per second, 1 to 30) and adds it to the southern
// part of the frame.
private void addSlider() {
final JSlider slider = new JSlider(1, 30);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
timer.setDelay(1000 / slider.getValue());
}
});
// start at 20 frames per second
slider.setValue(20);
// create a panel for the slider and its slow/fast labels
JPanel p = new JPanel();
p.add(new JLabel("slow"));
p.add(slider);
p.add(new JLabel("fast"));
frame.add(p, "South");
}
}
Panel class AnimationPanel.java
-------------------------------
// This class draws each frame of the animation. It has a counter that goes
// from 0 up to MAX_COUNT, then back down to 0, then back up to MAX_COUNT, and
// so on. It uses the count to determine the font size (bigger count = bigger
// font).
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.util.*;
public class AnimationPanel extends JPanel {
private int count; // current count in animation
private boolean increasing; // is text is increasing in size?
public static final int MAX_COUNT = 10; // when animation reverses
// post: initializes the panel to the initial frame
public AnimationPanel() {
count = 0;
increasing = true;
setBackground(Color.MAGENTA);
}
// post: paints the next frame of the animation
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// set up font size based on current animation count and find the
// bounding rectangle of the text
int fontSize = 10 + 6 * count;
Font f = new Font("Serif", Font.BOLD, fontSize);
g.setFont(f);
String text = "Hello!";
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = f.getStringBounds(text, context);
// center the text within the panel and surround with 2 points of
// extra space
int x = (int) ((getWidth() - bounds.getWidth()) / 2.0);
int y = (getHeight() + fontSize) / 2;
bounds.setRect(x - 2, y - fontSize - 2, bounds.getWidth() + 4,
bounds.getHeight() + 4);
// use a background fill and draw the text over it
g2.setPaint(Color.CYAN);
g2.fill(bounds);
g2.setPaint(Color.BLACK);
g2.drawString(text, x, y);
// change direction if we've just hit the limit
if (count == MAX_COUNT)
increasing = false;
else if (count == 0)
increasing = true;
// update count
if (increasing)
count++;
else
count--;
}
}