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--; } }
Stuart Reges
Last modified: Mon Apr 2 16:27:29 PDT 2007