0

I've made a JTextField that restricts characters being entered unless it's numbers, letter "e", or comma . But now I realised that it restricts backspace being pressed to. How can I change it? I'll add the code, where it checks what key is being pressed, below

for (JTextField tf : listOfFields)
         {
             String value = tf.getText();
             int n = value.length();
             if (ke.getKeyChar()>= '0' &&  ke.getKeyChar() <= '9' || ke.getKeyChar() == ','|| ke.getKeyChar() == 'e')
             {
                 tf.setEditable(true);
             }
             else
             {
               tf.setEditable(false);
             }
         }}});
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
guilt
  • 49
  • 7
  • 1
    To filter what is allowed or not, I would suggest adding a `DocumentFilter` to the `Document` of the `JTextField` - e.g. https://stackoverflow.com/a/5663094/85421, https://stackoverflow.com/a/9478124/85421 – user85421 Nov 13 '19 at 13:27
  • It's much better to go to the `Document` and filter incoming edits. In fact, I think there is a slightly odd `DocumentFilter`. (Or what @CarlosHeuberger said 4 seconds before me.) – Tom Hawtin - tackline Nov 13 '19 at 13:27
  • Here is an example of a Document Filter that allows only inputs that match a regex https://gist.github.com/educostadev/8c468d1e7dbee6e59c4aaef81b3778e1 – Edu Costa Nov 13 '19 at 13:49

2 Answers2

2

To have a text field accept a numeric entry, you should use a JFormattedTextField:

JFormattedTextField field = new JFormattedTextField(
    NumberFormat.getIntegerInstance());
field.setColumns(12);

To make it check both a localized number format (one that uses commas) and also the java.lang syntax (like 1e5), you can create a NumberFormatter which does both:

NumberFormatter formatter = new NumberFormatter() {
    @Override
    public Object stringToValue(String text)
    throws ParseException {
        try {
            return Double.valueOf(text);
        } catch (NumberFormatException ne) {
            return super.stringToValue(text);
        }
    }
};
JFormattedTextField field = new JFormattedTextField(formatter);
field.setColumns(12);

Each field’s value can be retrieved with the getValue method:

for (JFormattedTextField tf : listOfFields) {
    Number value = (Number) tf.getValue();
    // ...
}

Restricting the keys typed by the user is not the correct way to guarantee numeric entry. For instance, your code would allow a user to type 123,4,45,678.

There are many keys which allow editing. Home, End, Delete, and Ctrl-A are just a few. You shouldn't try to explicitly accommodate them all with a keystroke whitelist. Let JFormattedTextField do the work of verifying the input.

VGR
  • 40,506
  • 4
  • 48
  • 63
0

If you really want to stick to this way of filtering, assuming ke is a KeyEvent, test the key code not the key char: add this condition

|| ke.getKeyCode()  == KeyEvent.VK_BACK_SPACE
StephaneM
  • 4,779
  • 1
  • 16
  • 33
  • I doubt it is so easy... as I remember `getKeyChar` only returns valid character for `KEY_TYPED` events, while `getKeyCode` for `KEY_PRESSED` and `KEY_RELEASED`, but **not** `KEY_TYPED` (should return `UNDEFINED`) - hard to know when this is being called without seeing whole code – user85421 Nov 13 '19 at 13:38
  • yes, memory still working: [KeyEvent](https://docs.oracle.com/en/java/javase/13/docs/api/java.desktop/java/awt/event/KeyEvent.html) : "...result of the getKeyChar method is guaranteed to be meaningful only for KEY_TYPED events..." and "... For key typed events, the getKeyCode method always returns VK_UNDEFINED..." – user85421 Nov 13 '19 at 13:44