Accept only numbers and a dot in Java TextField
Solution 1
As suggested by Oracle ,Use Formatted Text Fields
Formatted text fields provide a way for developers to specify the valid set of characters that can be typed in a text field.
amountFormat = NumberFormat.getNumberInstance();
...
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
Solution 2
I just use a try
-catch
block:
try {// if is number
Integer.parseInt(String);
} catch (NumberFormatException e) {
// else then do blah
}
Solution 3
JTextField txField = new DoubleJTextField();
Create a file DoubleJTextField.java and be happy
public class DoubleJTextField extends JTextField {
public DoubleJTextField(){
addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char ch = e.getKeyChar();
if (!isNumber(ch) && !isValidSignal(ch) && !validatePoint(ch) && ch != '\b') {
e.consume();
}
}
});
}
private boolean isNumber(char ch){
return ch >= '0' && ch <= '9';
}
private boolean isValidSignal(char ch){
if( (getText() == null || "".equals(getText().trim()) ) && ch == '-'){
return true;
}
return false;
}
private boolean validatePoint(char ch){
if(ch != '.'){
return false;
}
if(getText() == null || "".equals(getText().trim())){
setText("0.");
return false;
}else if("-".equals(getText())){
setText("-0.");
}
return true;
}
}
Solution 4
Don't ever use a KeyListener for this. Your code above has two serious bugs, both caused by the use of a KeyListener. First, it will miss any text that gets pasted in. Whenever I find a field that filters out non-digits, I always try to paste in some text, just for fun. Nine times out of ten, the text gets accepted, because they used a key listener.
Second, you didn't filter out modifiers. If the user tries to save their work by typing control-s while they're in this field, your key listener will consume the event. And if your application assigns, say, a control-5 or alt-5 shortcut to some action, this KeyListener will add a 5 to the field when they type it, even though the user wasn't trying to type a character. You did figure out that you needed to pass the backspace key, but that's not all you need to pass. Your arrow keys won't work. Neither will your function keys. You can fix all these problems, but it starts to be a lot of work.
There's a third disadvantage, but it only shows up if you adapt your application to a foreign alphabet, particularly one that takes multiple keystrokes to generate a single character, like Chinese. These alphabets make KeyListeners useless.
The trouble is this. You need to filter characters, but KeyListeners aren't about characters, they're about keystrokes, which are not the same thing: Not all keystrokes generate characters, and not all characters are generated by keystrokes. You need an approach that looks at characters after they've been generated, and after modified keystrokes have already been filtered out.
The simplest approach is to use a JFormattedTextField, but I've never liked that approach, because it doesn't format or filter as you type. So instead, I will use a DocumentFilter. DocumentFilters don't operate on keystrokes, they operate on the text strings as they get inserted to your JTextField's data model. Hence, all the control-keys, arrow and function keys and such don't even reach the DocumentFilter. All pasted text goes through the DocumentFilter, too. And, for languages that take three keystrokes to generate a single character, the DocumentFilter doesn't get invoked until the character is generated. Here's what it looks like:
ptoMinimoField = new JTextField();
ptoMinimoField.setBounds(348, 177, 167, 20); // Don't do this! See below.
contentPanel.add(ptoMinimoField);
ptoMinimoField.setColumns(10);
PlainDocument document = (PlainDocument) ptoMinimoField.getDocument();
document.setDocumentFilter(new DigitFilter());
}
The DigitFilter class looks like this:
public class DigitFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String text,
AttributeSet attr) throws BadLocationException {
super.insertString(fb, offset, revise(text), attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
super.replace(fb, offset, length, revise(text), attrs);
}
private String revise(String text) {
StringBuilder builder = new StringBuilder(text);
int index = 0;
while (index < builder.length()) {
if (accept(builder.charAt(index))) {
index++;
} else {
// Don't increment index here, or you'll skip the next character!
builder.deleteCharAt(index);
}
}
return builder.toString();
}
/**
* Determine if the character should remain in the String. You may
* override this to get any matching criteria you want.
* @param c The character in question
* @return true if it's valid, false if it should be removed.
*/
public boolean accept(final char c) {
return Character.isDigit(c) || c == '.';
}
}
You could write this as an inner class, but I created a separate class so you can override the accept() method to use any criteria you want. You may also notice that I don't test for digits by writing this:
(c < '0') || (c > '9')
Instead, I do this:
Character.isDigit()
This is faster, cleaner, and works with foreign numbering systems. I also don't need your test for the backspace character, '\b'. I'm guessing that your first KeyListener was filtering out the backspace key, which was your first clue that it was the wrong approach.
And on an unrelated note, don't hard code your component positions. Learn how to use the LayoutManagers. They're easy to use, and they'll make your code much easier to maintain.
Solution 5
Have you looked at a JFormattedTextField? It would seem it does what you want.
Agustín
I created my first web page at the age of 9 - it was dedicated to one of my favorite band. As any person’s first attempt at anything, it was not good. In fact, it was cringe-worthy bad, and I had never been so proud of anything in my life. It’s been such an enjoyable ride since then, doing what I love for a living and constantly learning more about it. I now have over 5 years’ experience in the development of web and mobile applications, both in frontend and backend side. I have an extensive knowledge of most used web technologies and frameworks such as HTML5, CSS3, JavaScript, Angular JS, Typescript, Node JS, Mongo DB, among many others. I’ve also been a part of a variety of demanding projects, ranging from small, local endeavors, to complex, international platforms and highly customized migrations working with Agile Methodologies. I’ve tried my hand at a number of challenges, becoming more flexible and versatile with every new lesson learnt. I’ve realized I’m most comfortable working in any-size international teams, as I’ve found I thrive in a collaborative environment
Updated on July 17, 2022Comments
-
Agustín almost 2 years
I've got one textField where I only accept numbers from the keyboard, but now I have to change it as it's a "price textField" and I would also need to accept a dot "." for any kind of prices.
How can I change this in order to get what I need?
ptoMinimoField = new JTextField(); ptoMinimoField.setBounds(348, 177, 167, 20); contentPanel.add(ptoMinimoField); ptoMinimoField.setColumns(10); ptoMinimoField.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent e) { char caracter = e.getKeyChar(); if (((caracter < '0') || (caracter > '9')) && (caracter != '\b')) { e.consume(); } } });
-
mKorbel almost 11 yearsthis is preimplamanted in DocumentFilter (for pattern as paramater), maybe I'm wrong (in this form)
-
kleopatra over 10 yearswhatever the question, keyListeners are the wrong approach. Particularly for restricting allowable input: they can't handle pasted text ..
-
kleopatra over 10 yearsthere's no keyEvent to consume because a keyListener is the wrong approach ;-) No downvote, though, as the code could be used in a DocumentFilter as @mKorbel already suggested
-
msrd0 over 9 yearsI think the OP wanted to accept numbers and dots.
Integer.parseInt
will throw anNumberFormatException
if the input was 1.2 or similar -
gsamaras about 9 yearsAdd some explanation to your answer.
-
MiguelMunoz over 7 yearsKeyListeners are a bad approach to this kind of problem.
-
MiguelMunoz over 7 yearsThis code is buggy. If the user is in the field and types a function key, or types a control or alt key, that keystroke will get consumed, and the command won't get executed. Also, this will miss text that gets pasted in. Stay away from KeyListeners for this kind of thing.
-
MiguelMunoz over 7 yearsThis code is buggy. If the user is in the field and types a function key, or types a control or alt key, that keystroke will get consumed, and the command won't get executed. Also, this will miss text that gets pasted in.
-
MiguelMunoz over 7 yearsThis code is buggy. If the user is in the field and types a function key, or types a control or alt key, that keystroke will get consumed, and the command won't get executed. Also, this will miss text that gets pasted in. Stay away from KeyListeners for this kind of thing.
-
MiguelMunoz over 7 yearsThis code is buggy. If the user is in the field and types a function key, or types a control or alt key, that keystroke will get consumed, and the command won't get executed. Also, this will miss text that gets pasted in. Stay away from KeyListeners for this kind of thing.
-
Cristian Babarusi almost 7 yearsthis is perfect answer... is that i was looking for... is working perfect on my application...this code allow me to type in that jtextfield only numbers simple or double...example 4.5 or 33. this is what i need. thanks very much for posting it.
-
MiguelMunoz about 5 yearsKeyListeners are about keystrokes, not characters. They cause all sorts of problems when you use keyboard modifiers or type keystrokes that don't generate characters like function and arrow keys. Write a DocumentFilter instead.
-
MiguelMunoz about 5 yearsWithout any error? You just didn't find them. This code filter out arrow keys, function keys, and keyboard shortcuts. And it fails to filter pasted text. A DocumentFilter has none of these problems. And you forgot to allow the dot. And BTW, calling Character.isDigit() is faster and works with foreign numbering systems.
-
MiguelMunoz about 5 yearsThey also block function keys, arrow keys, and menu shortcuts.
-
Himagaran about 5 yearshow to allow minus and decimal characters ('-' & '.') with this method?