Rawbutton

Main.java  [download]

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

/**
 * Main program for testing Rawbutton's
 */
public class Main extends JFrame implements MouseListener {
    public static void main (String [] args) {
	java.awt.EventQueue.invokeLater (new Runnable() {
            public void run() {
		new Main ();
            }
        });
    }

    private ArrayList<Rawbutton> buttons = new ArrayList<Rawbutton>();

    public Main () {
	// Window setup
	setSize (500, 500);
	Container content = getContentPane();
	content.setLayout (new FlowLayout());
	setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
	addMouseListener (this);

	// Create some Rawbutton's for testing
	buttons.add (new Rawbutton ("Push me", 100, 100)); //*1 Create and add just like a JButton
	buttons.add (new Rawbutton ("Me too", 300, 300)); //*1

	// And a CircleButton
	buttons.add (new CircleButton ("Circle", 100, 250)); //*1

	setVisible (true);
    }

    /**
     * Catch our paint callback and pass to our "components"
     * NB Swing calls paint() but not paintComponent() for this case.
     */
    public void paint (Graphics g) { //*2 We must dispatch the paint callbacks outside of Swing
	super.paint(g);

	for (Rawbutton b: buttons) //*2
	    b.draw (g); //*2
    }
	
    /**
     * Catch our mouse callback and call each of our "components" to
     * offer them the input
     */
    public void mousePressed (MouseEvent event) { //*3 We dispatch mouse callbacks too
	for (Rawbutton b: buttons) //*3
	    b.domouse (event.getPoint().x, event.getPoint().y); //*3
    }

    /**
     * Remaining required MouseListener methods
     */
    public void mouseClicked (MouseEvent event) {}
    public void mouseReleased (MouseEvent event) {}
    public void mouseEntered (MouseEvent event) {}
    public void mouseExited (MouseEvent event) {}
}

Rawbutton.java  [download]

import java.awt.*;
import java.awt.geom.*;

/**
 * Screen button, built without using a toolkit
 *
 * To use this, you must draw() it and domouse() it when needed
 */
public class Rawbutton { //*1 Object not JComponent
    /**
     * We remember our label, so can redraw
     */
    protected String label; //*2 We remember our label, use for redraw

    /**
     * We remember our location, for redraw *and* for testing mouse input
     */
    protected RectangularShape loc; //*3 We remember our location, use for redraw and mouse

    public Rawbutton (String label, int x, int y) {
	// Stash arg
	this.label = label; //*2

	// You tell us where, but we determine size
	loc = new Rectangle (x, y, 80, 30); //*3
    }

    /**
     * Our parent must call this when it's time to draw us
     */
    public void draw (Graphics g) { //*4 draw() and domouse() are dispatched to us outside of Swing
	Graphics2D g2 = (Graphics2D) g;

	// Background
	g2.setColor (Color.WHITE); //*5 Java2D function, works on other shapes too
	g2.fill (loc); //*5

	// Outline
	g2.setColor (Color.BLACK); //*5
	g2.draw (loc); //*5

	// Label
	g.drawString (label, (int)loc.getX()+10, (int)loc.getY()+25); //*2
    }

    /**
     * Our parent must call this when it gets a mouse click
     */
    public void domouse (int x, int y) { //*4
	if (loc.contains (x, y)) //*5
	    System.out.println ("You pressed the button labeled " + label); //*5
    }
}

CircleButton.java  [download]

import java.awt.*;
import java.awt.geom.*;

/**
 * Like Rawbutton, but circular
 */
public class CircleButton extends Rawbutton {
    public CircleButton (String label, int x, int y) {
	super (label, x, y);

	loc = new Ellipse2D.Double (x, y, 50, 50); //*1 Clobber the one that Rawbutton provided us
    }
}