Mega Code Archive

 
Categories / Java / Swing Components
 

JSpinField is a numeric field with 2 spin buttons to increase or decrease the value

/*  *  JSpinField.java  - A spin field using a JSpinner (JDK 1.4)  *  Copyright (C) 2004 Kai Toedter  *  kai@toedter.com  *  www.toedter.com  *  *  This program is free software; you can redistribute it and/or  *  modify it under the terms of the GNU Lesser General Public License  *  as published by the Free Software Foundation; either version 2  *  of the License, or (at your option) any later version.  *  *  This program is distributed in the hope that it will be useful,  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  *  GNU Lesser General Public License for more details.  *  *  You should have received a copy of the GNU Lesser General Public License  *  along with this program; if not, write to the Free Software  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ //package com.toedter.components; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /**  * JSpinField is a numeric field with 2 spin buttons to increase or decrease the  * value. It has the same interface as the "old" JSpinField but uses a JSpinner  * internally (since J2SE SDK 1.4) rather than a scrollbar for emulating the  * spin buttons.  *   * @author Kai Toedter  * @version $LastChangedRevision: 85 $  * @version $LastChangedDate: 2006-04-28 13:50:52 +0200 (Fr, 28 Apr 2006) $  */ public class JSpinField extends JPanel implements ChangeListener, CaretListener, ActionListener,     FocusListener {   private static final long serialVersionUID = 1694904792717740650L;   protected JSpinner spinner;   /** the text (number) field */   protected JTextField textField;   protected int min;   protected int max;   protected int value;   protected Color darkGreen;   /**    * Default JSpinField constructor. The valid value range is between    * Integer.MIN_VALUE and Integer.MAX_VALUE. The initial value is 0.    */   public JSpinField() {     this(Integer.MIN_VALUE, Integer.MAX_VALUE);   }   /**    * JSpinField constructor with given minimum and maximum vaues and initial    * value 0.    */   public JSpinField(int min, int max) {     super();     setName("JSpinField");     this.min = min;     if (max < min)       max = min;     this.max = max;     value = 0;     if (value < min)       value = min;     if (value > max)       value = max;     darkGreen = new Color(0, 150, 0);     setLayout(new BorderLayout());     textField = new JTextField();     textField.addCaretListener(this);     textField.addActionListener(this);     textField.setHorizontalAlignment(SwingConstants.RIGHT);     textField.setBorder(BorderFactory.createEmptyBorder());     textField.setText(Integer.toString(value));     textField.addFocusListener(this);     spinner = new JSpinner() {       private static final long serialVersionUID = -6287709243342021172L;       private JTextField textField = new JTextField();       public Dimension getPreferredSize() {         Dimension size = super.getPreferredSize();         return new Dimension(size.width, textField.getPreferredSize().height);       }     };     spinner.setEditor(textField);     spinner.addChangeListener(this);     // spinner.setSize(spinner.getWidth(), textField.getHeight());     add(spinner, BorderLayout.CENTER);   }   public void adjustWidthToMaximumValue() {     JTextField testTextField = new JTextField(Integer.toString(max));     int width = testTextField.getPreferredSize().width;     int height = testTextField.getPreferredSize().height;     textField.setPreferredSize(new Dimension(width, height));     textField.revalidate();   }   /**    * Is invoked when the spinner model changes    *     * @param e    *            the ChangeEvent    */   public void stateChanged(ChangeEvent e) {     SpinnerNumberModel model = (SpinnerNumberModel) spinner.getModel();     int value = model.getNumber().intValue();     setValue(value);   }   /**    * Sets the value attribute of the JSpinField object.    *     * @param newValue    *            The new value    * @param updateTextField    *            true if text field should be updated    */   protected void setValue(int newValue, boolean updateTextField, boolean firePropertyChange) {     int oldValue = value;     if (newValue < min) {       value = min;     } else if (newValue > max) {       value = max;     } else {       value = newValue;     }     if (updateTextField) {       textField.setText(Integer.toString(value));       textField.setForeground(Color.black);     }     if (firePropertyChange) {       firePropertyChange("value", oldValue, value);     }   }   /**    * Sets the value. This is a bound property.    *     * @param newValue    *            the new value    *     * @see #getValue    */   public void setValue(int newValue) {     setValue(newValue, true, true);     spinner.setValue(new Integer(value));   }   /**    * Returns the value.    *     * @return the value value    */   public int getValue() {     return value;   }   /**    * Sets the minimum value.    *     * @param newMinimum    *            the new minimum value    *     * @see #getMinimum    */   public void setMinimum(int newMinimum) {     min = newMinimum;   }   /**    * Returns the minimum value.    *     * @return the minimum value    */   public int getMinimum() {     return min;   }   /**    * Sets the maximum value and adjusts the preferred width.    *     * @param newMaximum    *            the new maximum value    *     * @see #getMaximum    */   public void setMaximum(int newMaximum) {     max = newMaximum;   }   /**    * Sets the horizontal alignment of the displayed value.    *     * @param alignment    *            the horizontal alignment    */   public void setHorizontalAlignment(int alignment) {     textField.setHorizontalAlignment(alignment);   }   /**    * Returns the maximum value.    *     * @return the maximum value    */   public int getMaximum() {     return max;   }   /**    * Sets the font property.    *     * @param font    *            the new font    */   public void setFont(Font font) {     if (textField != null) {       textField.setFont(font);     }   }   /**    * Sets the foreground    *     * @param fg    *            the foreground    */   public void setForeground(Color fg) {     if (textField != null) {       textField.setForeground(fg);     }   }   /**    * After any user input, the value of the textfield is proofed. Depending on    * being an integer, the value is colored green or red.    *     * @param e    *            the caret event    */   public void caretUpdate(CaretEvent e) {     try {       int testValue = Integer.valueOf(textField.getText()).intValue();       if ((testValue >= min) && (testValue <= max)) {         textField.setForeground(darkGreen);         setValue(testValue, false, true);       } else {         textField.setForeground(Color.red);       }     } catch (Exception ex) {       if (ex instanceof NumberFormatException) {         textField.setForeground(Color.red);       }       // Ignore all other exceptions, e.g. illegal state exception     }     textField.repaint();   }   /**    * After any user input, the value of the textfield is proofed. Depending on    * being an integer, the value is colored green or red. If the textfield is    * green, the enter key is accepted and the new value is set.    *     * @param e    *            Description of the Parameter    */   public void actionPerformed(ActionEvent e) {     if (textField.getForeground().equals(darkGreen)) {       setValue(Integer.valueOf(textField.getText()).intValue());     }   }   /**    * Enable or disable the JSpinField.    *     * @param enabled    *            The new enabled value    */   public void setEnabled(boolean enabled) {     super.setEnabled(enabled);     spinner.setEnabled(enabled);     textField.setEnabled(enabled);     /*      * Fixes the background bug      * 4991597 and sets the background explicitely to a      * TextField.inactiveBackground.      */     if (!enabled) {       textField.setBackground(UIManager.getColor("TextField.inactiveBackground"));     }   }   /**    * Returns the year chooser's spinner (which allow the focus to be set to    * it).    *     * @return Component the spinner or null, if the month chooser has no    *         spinner    */   public Component getSpinner() {     return spinner;   }   /**    * Creates a JFrame with a JSpinField inside and can be used for testing.    *     * @param s    *            The command line arguments    */   public static void main(String[] s) {     JFrame frame = new JFrame("JSpinField");     frame.getContentPane().add(new JSpinField());     frame.pack();     frame.setVisible(true);   }   /*    * (non-Javadoc)    *     * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)    */   public void focusGained(FocusEvent e) {   }   /**    * The value of the text field is checked against a valid (green) value. If    * valid, the value is set and a property change is fired.    */   public void focusLost(FocusEvent e) {     actionPerformed(null);   } }