Incdec4

Main.java  [download]

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

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

    private Incdec id1, id2;
    private JScrollBar sb;

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

	// Create some Incdec's for testing
	id1 = new Incdec ();
	id1.addAdjustmentListener (this); //*1 Use adjustmentListener instead of old get data button
	content.add (id1);

	// Demonstrate our setBorderColor
	id2 = new Incdec ();
	id2.setBorderColor (Color.GREEN);
	id2.addAdjustmentListener (this); //*1
	content.add (id2);

	// Try a scrollbar, 
	// to show how it shares same Adjustable interface with our Incdec
	sb = new JScrollBar ();
	sb.addAdjustmentListener (this); //*2 Same as a JScrollBar
	content.add (sb);

	setVisible (true);
    }

    /**
     * Catch our new callbacks from our Incdec's and our ScrollBar,
     * works the same for both, same AdjustmentEvent,
     * same e.getValue()
     */
    public void adjustmentValueChanged (AdjustmentEvent e) { //*3 Same callback from our synthesized widget OR real JScrollbar
	String source = null;
        if (e.getSource()==id1) source = "Incdec 1";
	else if (e.getSource()==id2) source = "Incdec 2";
	else if (e.getSource()==sb) source = "Scrollbar";

	System.out.println ("Adjustment value changed: " //*3
			    + source + " => " + e.getValue()); //*3
    }
}

Incdec.java  [download]

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

public class Incdec extends JPanel implements ActionListener, Adjustable { //*1 Catches ActionListener, Sends Adjustable
    /**
     * Our internal components that we need to remember
     */
    protected JButton upButton, downButton;
    protected JLabel label;

    /**
     * Our data, initialized inline here 
     */
    protected int value = 0;
    protected int min = 0;
    protected int max = 100;
    protected int incr = 1;

    public Incdec () {
	// Put a border on our JPanel
	// default color, user can modify later
	setBorder (new LineBorder(Color.RED, 1));

	// Use vertical grid layout to hold our buttons and stuff
	setLayout (new GridLayout (3, 1));
	
	// Our internal widgets:
	// Our up button
	upButton = new JButton ("+");
	upButton.addActionListener (this); //*2 Our internal callbacks
	add (upButton);

	// Our label widget
	label = new JLabel ();
	label.setHorizontalAlignment (JLabel.CENTER);
	refreshLabel ();
	add (label);

	// Our down button
	downButton = new JButton ("-");
	downButton.addActionListener (this); //*2
	add (downButton);
    }

    /**
     * Common callback for both internal buttons,
     * we use ivar to disambiguate.
     * Then we fire the result to *our* listeners.
     */
    public void actionPerformed (ActionEvent e) { //*2
	int type = 0;

        if (e.getSource()==upButton) {
	    value += incr;
	    type = AdjustmentEvent.UNIT_INCREMENT;
	}
	else if (e.getSource()==downButton) {
	    value -= incr;
	    type = AdjustmentEvent.UNIT_DECREMENT;
	}

	// Clamp at bounds
	if (value > max) value = max;
	if (value < min) value = min;

	// Update our label widget to match
	refreshLabel ();

	// Make a new event with our new data
	AdjustmentEvent event = new AdjustmentEvent (this, //*3 Create and fire our event (listenerList mechanism is inherited from JComponent)
	    AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, type, value); //*3

	// Send it to each of *our* listeners
	for (AdjustmentListener l: //*3
	    listenerList.getListeners (AdjustmentListener.class)) { //*3
		l.adjustmentValueChanged (event); //*3
	} //*3

    }

    /**
     * Common code fragment, extracted to here
     */
    protected void refreshLabel() {
	label.setText (String.valueOf (value));
	repaint ();
    }

    /**
     * Just as an example, we let user customize border color here
     */
    public void setBorderColor (Color color) {
	setBorder (new LineBorder(color, 1));
	repaint ();
    }

    /**
     * Methods required by Adjustable,
     * listenerList is an ivar of JComponent, we access it here
     */
    public void addAdjustmentListener(AdjustmentListener l) { //*4 Required by Adjustable, add/remove listener
	listenerList.add (AdjustmentListener.class, l); //*4
    }
    public void removeAdjustmentListener(AdjustmentListener l) { //*4
	listenerList.remove (AdjustmentListener.class, l); //*4
    }

    /**
     * Methods required by Adjustable,
     * though block vs. unit and visibleAmount don't really make sense for us 
     */
    public int getValue() { return value; } //*5 Required by Adjustable, do something reasonable
    public int getMaximum() { return max; } //*5
    public int getMinimum() { return min; } //*5
    public int getOrientation() { return VERTICAL; } //*5
    public int getUnitIncrement() { return incr; } //*5
    public int getBlockIncrement () { return incr; } //*5
    public int getVisibleAmount() { return 0; } //*5
    public void setBlockIncrement(int b) { incr = b; } //*5
    public void setMaximum(int max) { this.max = max; } //*5
    public void setMinimum(int min) { this.min = min; } //*5
    public void setUnitIncrement(int u) { incr = u; } //*5
    public void setVisibleAmount(int v) { } //*5

    public void setValue(int v) { //*5
	value = v; //*5
	refreshLabel (); //*5
    }
}