001/** 002 * Please feel free to use any fragment of the code in this file that you need 003 * in your own work. As far as I am concerned, it's in the public domain. No 004 * permission is necessary or required. Credit is always appreciated if you 005 * use a large chunk or base a significant product on one of my examples, 006 * but that's not required either. 007 * 008 * This code is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 011 * 012 * --- Joseph A. Huwaldt 013 */ 014package jahuwaldt.swing; 015 016import javax.swing.*; 017import java.awt.Toolkit; 018import java.text.*; 019 020/** 021 * A text field that validates it's input and only accepts inputs that are a valid decimal 022 * number such as 3.14159. The user of this class provides the NumberFormat object that 023 * actually does the parsing and formatting for display. 024 * 025 * <p> Modified by: Joseph A. Huwaldt </p> 026 * 027 * @author Joseph A. Huwaldt, Date: February 24, 2000 028 * @version August 3, 2018 029 */ 030@SuppressWarnings("serial") 031public class DecimalField extends JTextField { 032 033 // The format object that parses and formats this text field's value. 034 private final NumberFormat format; 035 036 /** 037 * Constructor that takes the number of columns to be displayed, and a number format 038 * object to do the text formatting. The text field display is initially set to blank. 039 * 040 * @param columns The number of columns to use in the text field. 041 * @param nf The number format object to use for formatting the display of this 042 * text field. 043 */ 044 @SuppressWarnings("OverridableMethodCallInConstructor") 045 public DecimalField(int columns, NumberFormat nf) { 046 super(columns); 047 048 setDocument(new FormattedDocument(nf)); 049 format = nf; 050 setText(""); 051 } 052 053 /** 054 * Constructor that takes a value to be displayed, the number of columns to be 055 * displayed, and a number format object to do the text formatting. 056 * 057 * @param value The value to be displayed in the text field. 058 * @param columns The number of columns to use in the text field. 059 * @param nf The number format object to use for formatting the display of this 060 * text field. 061 */ 062 @SuppressWarnings("OverridableMethodCallInConstructor") 063 public DecimalField(double value, int columns, NumberFormat nf) { 064 super(columns); 065 066 setDocument(new FormattedDocument(nf)); 067 format = nf; 068 setValue(value); 069 } 070 071 /** 072 * Return the value represented by the text in this text field. If the text field is 073 * empty, Double.NaN is returned. 074 * 075 * @return The value represented by the text in this text field. 076 */ 077 public double getValue() { 078 double retVal = 0.0; 079 String text = getText(); 080 081 // Check for blank entries. 082 if (text == null || text.length() == 0) 083 return Double.NaN; 084 085 // Deal with special case of percentage format. 086 if (format instanceof DecimalFormat) { 087 String suffix = ((DecimalFormat)format).getPositiveSuffix(); 088 if (suffix.contains("%") && !text.endsWith("%")) 089 text += "%"; 090 } 091 092 try { 093 retVal = format.parse(text).doubleValue(); 094 095 } catch (ParseException e) { 096 // This should never happen because insertString allows 097 // only properly formatted data to get in the field. 098 Toolkit.getDefaultToolkit().beep(); 099 System.err.println("getValue: could not parse: " + text); 100 } 101 102 return retVal; 103 } 104 105 /** 106 * Set the text in this text field to the specified value. 107 * 108 * @param value The value to place in the text field. 109 */ 110 public final void setValue(double value) { 111 setText(format.format(value)); 112 } 113 114}