import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; public class Incdec extends JPanel implements ActionListener { //*1 We ARE a JPanel /** * Our internal components that we need to remember */ protected JButton upButton, downButton; //*2 We HAVE JButtons and JLabel protected JLabel label; //*2 /** * Our data, initialized inline here */ protected int value = 0; //*5 Maintain and report our data value 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 ("+"); //*2 upButton.addActionListener (this); //*3 We catch callbacks from both of our internal widgets add (upButton); // Our label widget label = new JLabel (); //*2 label.setHorizontalAlignment (JLabel.CENTER); refreshLabel (); add (label); // Our down button downButton = new JButton ("-"); //*2 downButton.addActionListener (this); //*3 add (downButton); } /** * Common callback for both buttons, * we use ivar to disambiguate. */ public void actionPerformed (ActionEvent e) { //*3 if (e.getSource()==upButton) value += incr; //*3 else if (e.getSource()==downButton) value -= incr; //*3 // Clamp at bounds if (value > max) value = max; if (value < min) value = min; // Update our label widget to match refreshLabel (); //*4 Update our label widget } /** * Common code fragment, extracted to here */ protected void refreshLabel() { //*4 label.setText (String.valueOf (value)); //*4 } /** * Just as an example, we let user customize border color here */ public void setBorderColor (Color color) { setBorder (new LineBorder(color, 1)); } public int getValue() { return value; } //*5 }