import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; import java.lang.reflect.*; /** * @author Owen Astrachan */ public class Bouncy2 extends JFrame { Bouncy2() { super("bounce.edu"); init(); pack(); setVisible(true); } public void init() { int bouncerCount = 1; // default is 2 myDim = new Dimension(400,400); Container content= getContentPane(); content.setLayout(new BorderLayout()); myButtonPanel = new JPanel(); myBouncerPanel = new BouncerPanel(); myTimer = new Timer(20,myBouncerPanel); myBouncerPanel.setPreferredSize( new Dimension(myDim.width, (int) (myDim.height*.80))); myButtonPanel.setPreferredSize( new Dimension(myDim.width, (int) (myDim.height*.20))); makeButtons(); makeColorBox(); content.add(BorderLayout.CENTER, myBouncerPanel); content.add(BorderLayout.NORTH, myButtonPanel); content.add(BorderLayout.SOUTH, myColorChoice); // add bouncers int k; for(k=0; k < bouncerCount; k++) { makeBouncer(myBouncerPanel,myColor); } // add mouselistener myBouncerPanel.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent me) { if (myFrozen) { myFrozen = false; startAnimation(); } else { myFrozen = true; stopAnimation(); } } }); } void makeButtons() { JButton adderB = new JButton("bouncer"); adderB.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { makeBouncer(myBouncerPanel,myColor); } }); myButtonPanel.add(adderB); JButton qb = new JButton("quit"); qb.addActionListener(Quitter.getInstance()); myButtonPanel.add(qb); } void makeColorBox() { Class c = null; try{ c = Class.forName("java.awt.Color"); } catch (ClassNotFoundException e) { System.err.println("could not load colors "+e); } // find all fields (static) in java.awt.Color // then put names of fields in an array Field[] colorFields = c.getFields(); Color[] colors = new Color[1]; Vector vcolors = new Vector(); for(int k = 0; k < colorFields.length; k++) { Field f = colorFields[k]; String name = f.getName(); Color tempColor = Color.red; // some default value try{ tempColor = (Color) f.get(null); // value of field vcolors.add(tempColor); } catch(Exception e){ // not a color, ignore it } } colors = (Color[]) vcolors.toArray(colors); ColorBoxRenderer render= new ColorBoxRenderer(); render.setPreferredSize(new Dimension(100,20)); myColorChoice = new JComboBox(colors); myColorChoice.setRenderer(render); myColorChoice.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { myColor = (Color) ((JComboBox) e.getSource()).getSelectedItem(); } } ); myColorChoice.setBorder( BorderFactory.createTitledBorder("Choose Color")); myButtonPanel.add(myColorChoice); } /** * make and return a Bouncer object * @param widget is where the bouncer lives */ Bouncer makeBouncer(Container widget,Color c) { int startx = (int) (Math.random()*widget.getWidth()); int starty = (int) (Math.random()*widget.getHeight()); Bouncer b = new Bouncer(startx,starty,c,widget); getContentPane().setVisible(false); widget.setVisible(false); /*** ImageBouncer b2 = myBcount % 2 == 0 ? new ImageBouncer(startx/2,starty/3,c,widget, "olasmall.gif") : new ImageBouncer(startx/2,starty/3,c,widget, "rcd_old.gif"); myBcount++; widget.add(b2); **/ widget.add(b); widget.setVisible(true); getContentPane().setVisible(true); // ((JComponent)getContentPane()).revalidate(); ((JComponent)getContentPane()).repaint(); return b; } public synchronized void startAnimation() { if (! myFrozen && ! myTimer.isRunning()) { myTimer.start(); System.out.println("starting"); } } public synchronized void stopAnimation() { if (myTimer.isRunning()) { myTimer.stop(); System.out.println("stopping"); } } /* methods below are for the controller aspects of this * class -- note, not in separate class because this is * a short example, but these are kept separated as functions * called/used by widgets */ public static void main(String args[]) { Bouncy2 b = new Bouncy2(); b.startAnimation(); } private Timer myTimer; private Dimension myDim; private JPanel myButtonPanel; private BouncerPanel myBouncerPanel; private JComboBox myColorChoice; private Color myColor = Color.red; private boolean myFrozen = false; static private int myBcount = 0; } /** * a bouncing object that knows how to paint itself * by moving and how to display itself * this is a lightweight compoenent (no peer) * whose coordinates are container-based */ class Bouncer extends JComponent { /** * @param x is the initial x coordinate * @param y is the initial y coordinate * @param c is the color of the bouncer * @param widget is the container in which the bouncer will move */ Bouncer(int x, int y, Color c, Container widget) { myX = x; myY = y; myDX=8; myDY=5; myContainer = widget; myColor = c; myNumber = ourCount++; myDim = new Dimension(DIAMETER,DIAMETER); } public void act() { // bounce off a wall in x direction if (( (myX - RAD + myDX) < 0) || ( (myX + RAD + myDX) > myContainer.getWidth())) { myDX = - myDX; } // bounce off a wall in y direction if ((myY - RAD + myDY < 0) || (myY + RAD + myDY > myContainer.getHeight())) { myDY = - myDY; } myX += myDX; myY += myDY; // setLocation(myX,myY); } /** * paint where the object is */ public void paintComponent(Graphics g) { // draw self in my color super.paintComponent(g); doDraw(g); } public void doDraw(Graphics g) { g.setColor(myColor); g.fillOval(myX,myY,DIAMETER,DIAMETER); } public Point getLocation() { return new Point(myX,myY); } public Rectangle getBounds() { Rectangle r = new Rectangle(myX,myY,DIAMETER,DIAMETER); return r; } public Dimension getPreferredSize() { return myDim; } public Dimension getMinimumSize() { return myDim; } int myX,myY,myDX,myDY; // my coordinates and deltas Container myContainer; // where I live Color myColor; // my color int myNumber; // number of this bouncer (over all bouncers) Dimension myDim; // dimension of the bouncer static int ourCount = 0; public static final int RAD = 5; public static final int DIAMETER = 2*RAD; } class ImageBouncer extends Bouncer { ImageBouncer(int x, int y, Color c, Container widget, String name) { super(x,y,Color.white,widget); myImage = new TapImage(name,50); myDim = myImage.getPreferredSize(); } public void doDraw(Graphics g) { myImage.setBounds(getBounds()); myImage.paintComponent(g); } public Rectangle getBounds() { Rectangle r = new Rectangle(myX,myY, myImage.getPreferredSize().width, myImage.getPreferredSize().height); return r; } TapImage myImage; } /** * a quitting class, used when windows are closed or * quit menu item chosen (or any other quit action event) *

* * pattern: uses singleton for one instance per program *

* * inheritance: subclasses can override doQuit() for application-specific * cleanup * * @author Owen Astrachan */ class Quitter extends WindowAdapter implements ActionListener { public static Quitter getInstance() { if (ourInstance == null) { ourInstance = new Quitter(); } return ourInstance; } private Quitter() { // private constructor, creatable only through getInstance } public void windowClosing(WindowEvent e) { doQuit(); } public void actionPerformed(ActionEvent e) { doQuit(); } /** * the function called for any quit event, e.g., window closing * or quit menu item for chosen */ protected void doQuit() { System.exit(0); } private static Quitter ourInstance = null; } /** * */ class BouncerPanel extends JPanel implements ActionListener { BouncerPanel() { myBouncers = new Vector(); setBorder(BorderFactory.createEtchedBorder()); setLayout(null); } public Component add(Component comp) { super.add(comp); myBouncers.add(comp); ( (Bouncer)comp).act(); return comp; } public void animate() { int k; int size = myBouncers.size(); for(k=0; k < size; k++) { ( (Bouncer) myBouncers.get(k)).act(); } } public void paintComponent(Graphics g) { super.paintComponent(g); for(int k=0; k < myBouncers.size(); k++) { ( (Bouncer) myBouncers.get(k)).doDraw(g); } } public void actionPerformed(ActionEvent e) { animate(); repaint(); } private Vector myBouncers; } class ColorBoxRenderer extends JLabel implements ListCellRenderer { public ColorBoxRenderer() { setOpaque(true); } public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setBackground((Color)value); setForeground((Color)value); myColor = getBackground(); return this; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(myColor); g.fillRect(0,0,getWidth(),getHeight()); } private Color myColor; }