Is there any way to accept only numeric values in a JTextField
? Is there any special method for this?
Although there is the pure evil JFormattedTextField
there isn't a trivial way to do it using only the Swing library. The best way to implement this sort of feature is with a DocumentFilter
.
Some code I prepared earlier. A bit of description.
DataTF.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent eve) {
String AllowedData="0123456789.";
char enter = eve.getKeyChar();
if (!AllowedData.contains(String.valueOf(enter))) {
eve.consume();
}
}
});
Try this out in the key pressed event for the related JTextField.
private void JTextField(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
char enter = evt.getKeyChar();
if(!(Character.isDigit(enter))){
evt.consume();
}
}
Use formatter
to format text field.
NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed(false);
NumberFormatter formatter = new NumberFormatter(format);
formatter.setValueClass(Integer.class);
formatter.setMaximum(65535);
formatter.setAllowsInvalid(false);
formatter.setCommitsOnValidEdit(true);
myTextField = new JFormattedTextField(formatter);
import javax.swing.*;
import javax.swing.text.*;
public class JNumberTextField extends JTextField
{
private static final char DOT = '.';
private static final char NEGATIVE = '-';
private static final String BLANK = "";
private static final int DEF_PRECISION = 2;
public static final int NUMERIC = 2;
public static final int DECIMAL = 3;
public static final String FM_NUMERIC = "0123456789";
public static final String FM_DECIMAL = FM_NUMERIC + DOT;
private int maxLength = 0;
private int format = NUMERIC;
private String negativeChars = BLANK;
private String allowedChars = null;
private boolean allowNegative = false;
private int precision = 0;
protected PlainDocument numberFieldFilter;
public JNumberTextField()
{
this( 10, NUMERIC );
}
public JNumberTextField( int maxLen )
{
this( maxLen, NUMERIC );
}
public JNumberTextField( int maxLen, int format )
{
setAllowNegative( true );
setMaxLength( maxLen );
setFormat( format );
numberFieldFilter = new JNumberFieldFilter();
super.setDocument( numberFieldFilter );
}
public void setMaxLength( int maxLen )
{
if (maxLen > 0)
maxLength = maxLen;
else
maxLength = 0;
}
public int getMaxLength()
{
return maxLength;
}
public void setPrecision( int precision )
{
if ( format == NUMERIC )
return;
if ( precision >= 0 )
this.precision = precision;
else
this.precision = DEF_PRECISION;
}
public int getPrecision()
{
return precision;
}
public Number getNumber()
{
Number number = null;
if ( format == NUMERIC )
number = new Integer(getText());
else
number = new Double(getText());
return number;
}
public void setNumber( Number value )
{
setText(String.valueOf(value));
}
public int getInt()
{
return Integer.parseInt( getText() );
}
public void setInt( int value )
{
setText( String.valueOf( value ) );
}
public float getFloat()
{
return ( new Float( getText() ) ).floatValue();
}
public void setFloat(float value)
{
setText( String.valueOf( value ) );
}
public double getDouble()
{
return ( new Double( getText() ) ).doubleValue();
}
public void setDouble(double value)
{
setText( String.valueOf(value) );
}
public int getFormat()
{
return format;
}
public void setFormat(int format)
{
switch ( format )
{
case NUMERIC:
default:
this.format = NUMERIC;
this.precision = 0;
this.allowedChars = FM_NUMERIC;
break;
case DECIMAL:
this.format = DECIMAL;
this.precision = DEF_PRECISION;
this.allowedChars = FM_DECIMAL;
break;
}
}
public void setAllowNegative( boolean value )
{
allowNegative = value;
if ( value )
negativeChars = "" + NEGATIVE;
else
negativeChars = BLANK;
}
public boolean isAllowNegative()
{
return allowNegative;
}
public void setDocument( Document document )
{
}
class JNumberFieldFilter extends PlainDocument
{
public JNumberFieldFilter()
{
super();
}
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException
{
String text = getText(0,offset) + str + getText(offset,(getLength() - offset));
if ( str == null || text == null )
return;
for ( int i=0; i<str.length(); i++ )
{
if ( ( allowedChars + negativeChars ).indexOf( str.charAt(i) ) == -1)
return;
}
int precisionLength = 0, dotLength = 0, minusLength = 0;
int textLength = text.length();
try
{
if ( format == NUMERIC )
{
if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
new Long(text);
}
else if ( format == DECIMAL )
{
if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
new Double(text);
int dotIndex = text.indexOf(DOT);
if( dotIndex != -1 )
{
dotLength = 1;
precisionLength = textLength - dotIndex - dotLength;
if( precisionLength > precision )
return;
}
}
}
catch(Exception ex)
{
return;
}
if ( text.startsWith( "" + NEGATIVE ) )
{
if ( !allowNegative )
return;
else
minusLength = 1;
}
if ( maxLength < ( textLength - dotLength - precisionLength - minusLength ) )
return;
super.insertString( offset, str, attr );
}
}
}
Concidering the number of views this question is getting, i found none of the above solution suitable for my problem. I decided to make a custom PlainDocument to fit my needs. This solution also makes a beep sound when the maximum number of characters used is reached, or the inserted text is not an integer.
private class FixedSizeNumberDocument extends PlainDocument
{
private JTextComponent owner;
private int fixedSize;
public FixedSizeNumberDocument(JTextComponent owner, int fixedSize)
{
this.owner = owner;
this.fixedSize = fixedSize;
}
@Override
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException
{
if (getLength() + str.length() > fixedSize) {
str = str.substring(0, fixedSize - getLength());
this.owner.getToolkit().beep();
}
try {
Integer.parseInt(str);
} catch (NumberFormatException e) {
// inserted text is not a number
this.owner.getToolkit().beep();
return;
}
super.insertString(offs, str, a);
}
}
implented as follows:
JTextField textfield = new JTextField();
textfield.setDocument(new FixedSizeNumberDocument(textfield,5));