CIT 591 Bouncing Ball
Fall 2008, David Matuszek
Here is the Bouncing Ball program, as presented on this PowerPoint presentation. I have made some changes in the code, marked in red, to convert the example from an applet into an application.
Normal Java style is to put each class in a separate file. For convenience
in downloading and running, I have put all three classes into a single
file. This file should be named Controller.java and put into
the default package.
import java.awt.*;
import java.awt.event.*;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
public class Controller extends JFrame { // Changed from JApplet
JPanel buttonPanel = new JPanel();
JButton runButton = new JButton("Run");
JButton stopButton = new JButton("Stop");
Timer timer;
Model model = new Model();
View view = new View(model); // View must know about Model
// Added main method to convert applet into application
public static void main(String[] args) {
Controller c = new Controller();
c.init();
c.setSize(300, 300);
c.setVisible(true);
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void init() {
layOutComponents();
attachListenersToComponents();
// Connect model and view
model.addObserver(view);
}
private void layOutComponents() {
setLayout(new BorderLayout());
this.add(BorderLayout.SOUTH, buttonPanel);
buttonPanel.add(runButton);
buttonPanel.add(stopButton);
stopButton.setEnabled(false);
this.add(BorderLayout.CENTER, view);
}
private void attachListenersToComponents() {
runButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
runButton.setEnabled(false);
stopButton.setEnabled(true);
timer = new Timer(true);
timer.schedule(new Strobe(), 0, 40); // 25 times a second
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
runButton.setEnabled(true);
stopButton.setEnabled(false);
timer.cancel();
}
});
}
private class Strobe extends TimerTask { // An inner class
public void run() {
model.setLimits(view.getWidth(), view.getHeight());
model.makeOneStep();
}
}
}
//---------------------------------------------------------------------
class Model extends Observable {
public final int BALL_SIZE = 20;
private int xPosition = 0;
private int yPosition = 0;
private int xLimit, yLimit;
private int xDelta = 6;
private int yDelta = 4;
public void setLimits(int xLimit, int yLimit) {
this.xLimit = xLimit - BALL_SIZE;
this.yLimit = yLimit - BALL_SIZE;
}
public int getX() {
return xPosition;
}
public int getY() {
return yPosition;
}
public void makeOneStep() {
// Do the work
xPosition += xDelta;
if (xPosition < 0 || xPosition >= xLimit) {
xDelta = -xDelta;
xPosition += xDelta;
}
yPosition += yDelta;
if (yPosition < 0 || yPosition >= yLimit) {
yDelta = -yDelta;
yPosition += yDelta;
}
// Notify observers
setChanged();
notifyObservers();
}
}
//---------------------------------------------------------------------
class View extends JPanel implements Observer { // changed from Panel
Model model;
View(Model model) {
this.model = model;
}
public void paint(Graphics g) {
// Added because of differences between Panel and JPanel
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.red);
g.fillOval(model.getX(), model.getY(),
model.BALL_SIZE, model.BALL_SIZE);
}
public void update(Observable obs, Object arg) {
repaint();
}
}