![]() |
This program does a simple animation. Animation is done by creating a timer which calls an ActionListener at fixed intervals (eg, every 30 milliseconds). The listener makes some changes (eg, the ball coordinates) and calls the JPanel repaint() (which calls our paintComponent() method indirectly), which uses the updated coordinates to redraw the ball. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// animation/bb/BBDemo.java - ball bouncing in a box.
// -- Fred Swartz, December 2004
// Possible extensions: faster/slower button, ...
import javax.swing.JFrame;
///////////////////////////////////////////////////////////////////// BBDemo
public class BBDemo {
//================================================================= main
public static void main(String[] args) {
JFrame win = new JFrame("Bouncing Ball Demo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setContentPane(new BBPanel());
win.pack();
win.setVisible(true);
}//endmethod main
}//endclass BBDemo
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// animation/bb/BBPanel.java - Panel with buttons and box.
// Fred Swartz - December 2004
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/////////////////////////////////////////////////////////////////// BBPanel
class BBPanel extends JPanel {
BallInBox m_bb; // The bouncing ball panel
//========================================================== constructor
/** Creates a panel with the controls and bouncing ball display. */
BBPanel() {
//-- Create components
m_bb = new BallInBox();
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
//-- Layout inner panel with two buttons horizontally
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
//-- Layout outer panel with button panel above bouncing ball
this.setLayout(new BorderLayout());
this.add(buttonPanel, BorderLayout.NORTH);
this.add(m_bb , BorderLayout.CENTER);
//-- Add Listeners
startButton.addActionListener(new StartAction());
stopButton.addActionListener(new StopAction());
}//end constructor
////////////////////////////////////// inner listener class StartAction
class StartAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
m_bb.setAnimation(true);
}
}//end inner listener class StartAction
//////////////////////////////////////// inner listener class StopAction
class StopAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
m_bb.setAnimation(false);
}
}//end inner listener class StartAction
}//endclass BBPanel
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
// animation/bb/BouncingBall.java - A ball bouncing in a box.
// Fred Swartz - December 2004
// Animation is done by changing instance variables
// in a timer's actionListener, then calling repaint().
// * This panel has a simple model for movement: changing
// the x and y values each time the timer fires.
// * Flicker can be reduced by drawing into a BufferedImage,
// and/or using a clip region.
// * The edge of the oval could be antialiased (using Graphics2).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/////////////////////////////////////////////////////////////// BouncingBall
public class BallInBox extends JPanel {
//============================================== fields
//... Instance variables representing the ball.
private Ball m_ball = new Ball(0, 0);
private int m_ballDiameter = m_ball.getDiameter();
//... Instance variables for the animiation
private int m_velocityX = 2; // Initial x velocity (pixels/interval)
private int m_velocityY = 3; // Initial y velocity
private int m_interval = 30; // Milliseconds between updates.
private Timer m_timer; // Ball moves every time
//========================================================== constructor
/** Sets panel size and creates timer. */
public BallInBox() {
setPreferredSize(new Dimension(200, 80));
setBorder(BorderFactory.createLineBorder(Color.BLACK));
m_timer = new Timer(m_interval, new TimerListener());
}//end constructor
//========================================================= setAnimation
/** Turns the animation on or off.
*@param turnOnOff Specifies state of animation.
*/
public void setAnimation(boolean turnOnOff) {
if (turnOnOff) {
m_timer.start(); // start animation by starting the timer.
} else {
m_timer.stop(); // stop timer
}
}//end setAnimation
//======================================================= paintComponent
public void paintComponent(Graphics g) {
super.paintComponent(g); // Paint background, border
m_ball.draw(g); // Draw the ball.
}//end method paintComponent
//////////////////////////////////// inner listener class ActionListener
class TimerListener implements ActionListener {
//================================================== actionPerformed
/** ActionListener of the timer. Each time this is called,
* the ball's position is updated, creating the appearance of
* movement.
*@param e This ActionEvent parameter is unused.
*/
public void actionPerformed(ActionEvent e) {
//... Get the the current size of the Panel, ball bounds.
int rightBound = getWidth() - m_ballDiameter;
int bottomBound= getHeight()- m_ballDiameter;
//--- Compute new x position, check for passing over edge.
int nextX = m_ball.getX() + m_velocityX; // Move in x direction.
if (nextX < 0) { // If at or beyond left side
nextX = 0; // Place against edge and
m_velocityX = -m_velocityX; // reverse direction.
} else if (nextX > rightBound) { // If at or beyond right side
nextX = rightBound; // Place against right edge.
m_velocityX = -m_velocityX; // Reverse direction.
}
//--- Compute new y position analogous to x above.
int nextY = m_ball.getY() + m_velocityY;
if (nextY < 0) { // if we're at top
nextY = 0;
m_velocityY = -m_velocityY;
} else if (nextY > bottomBound) { // if we're at bottom
nextY = bottomBound;
m_velocityY = -m_velocityY;
}
//... Move ball to new position.
m_ball.setPosition(nextX, nextY);
// repaint() must be used to indirectly call paintComponent..
repaint(); // Repaint the panel
}//end actionPerformed
}//end inner class listener
}//endclass
|
This class holds the information about the ball, currently only its position and diamter, but other attributes are possible (eg, color). This ball knows nothing about animation, but it might be reasonable to move the velocity information from the animation code above into Ball.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// animation/bb/BallModel.java - The logic / model of a ball.
// Fred Swartz - December 2004
import java.awt.*;
///////////////////////////////////////////////////////////////// BallModel
public class Ball {
final static int DIAMETER = 21;
int m_x;
int m_y;
//======================================================== constructor
public Ball(int x, int y) {
m_x = x;
m_y = y;
}
//============================================================== draw
public void draw(Graphics g) {
g.fillOval(m_x, m_y, DIAMETER, DIAMETER);
}
//============================================= getDiamter, getX, getY
public int getDiameter() { return DIAMETER;}
public int getX() { return m_x;}
public int getY() { return m_y;}
//======================================================== setPosition
public void setPosition(int x, int y) {
m_x = x;
m_y = y;
}
}
|