Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the recommended way to make a numeric TextField in JavaFX?

I need to restrict input into a TextField to integers. Any advice?

like image 706
Harry Mitchell Avatar asked Sep 26 '11 13:09

Harry Mitchell


2 Answers

Very old thread, but this seems neater and strips out non-numeric characters if pasted.

// force the field to be numeric only textField.textProperty().addListener(new ChangeListener<String>() {     @Override     public void changed(ObservableValue<? extends String> observable, String oldValue,          String newValue) {         if (!newValue.matches("\\d*")) {             textField.setText(newValue.replaceAll("[^\\d]", ""));         }     } }); 
like image 99
Evan Knowles Avatar answered Sep 18 '22 16:09

Evan Knowles


javafx.scene.control.TextFormatter

Updated Apr 2016

This answer was created some years ago and the original answer is largely obsolete now.

Since Java 8u40, Java has a TextFormatter which is usually best for enforcing input of specific formats such as numerics on JavaFX TextFields:

  • Numeric TextField for Integers in JavaFX 8 with TextFormatter and/or UnaryOperator
  • Java 8 U40 TextFormatter (JavaFX) to restrict user input only for decimal number
  • String with numbers and letters to double javafx

See also other answers to this question which specifically mention TextFormatter.


Original Answer

There are some examples of this in this gist, I have duplicated one of the examples below:

// helper text field subclass which restricts text input to a given range of natural int numbers // and exposes the current numeric int value of the edit box as a value property. class IntField extends TextField {   final private IntegerProperty value;   final private int minValue;   final private int maxValue;     // expose an integer value property for the text field.   public int  getValue()                 { return value.getValue(); }   public void setValue(int newValue)     { value.setValue(newValue); }   public IntegerProperty valueProperty() { return value; }        IntField(int minValue, int maxValue, int initialValue) {     if (minValue > maxValue)        throw new IllegalArgumentException(         "IntField min value " + minValue + " greater than max value " + maxValue       );     if (!((minValue <= initialValue) && (initialValue <= maxValue)))        throw new IllegalArgumentException(         "IntField initialValue " + initialValue + " not between " + minValue + " and " + maxValue       );       // initialize the field values.     this.minValue = minValue;     this.maxValue = maxValue;     value = new SimpleIntegerProperty(initialValue);     setText(initialValue + "");       final IntField intField = this;       // make sure the value property is clamped to the required range     // and update the field's text to be in sync with the value.     value.addListener(new ChangeListener<Number>() {       @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {         if (newValue == null) {           intField.setText("");         } else {           if (newValue.intValue() < intField.minValue) {             value.setValue(intField.minValue);             return;           }             if (newValue.intValue() > intField.maxValue) {             value.setValue(intField.maxValue);             return;           }             if (newValue.intValue() == 0 && (textProperty().get() == null || "".equals(textProperty().get()))) {             // no action required, text property is already blank, we don't need to set it to 0.           } else {             intField.setText(newValue.toString());           }         }       }     });       // restrict key input to numerals.     this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {       @Override public void handle(KeyEvent keyEvent) {         if(intField.minValue<0) {                 if (!"-0123456789".contains(keyEvent.getCharacter())) {                     keyEvent.consume();                 }             }             else {                 if (!"0123456789".contains(keyEvent.getCharacter())) {                     keyEvent.consume();                 }             }       }     });            // ensure any entered values lie inside the required range.     this.textProperty().addListener(new ChangeListener<String>() {       @Override public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {         if (newValue == null || "".equals(newValue) || (intField.minValue<0 && "-".equals(newValue))) {           value.setValue(0);           return;         }           final int intValue = Integer.parseInt(newValue);           if (intField.minValue > intValue || intValue > intField.maxValue) {           textProperty().setValue(oldValue);         }                    value.set(Integer.parseInt(textProperty().get()));       }     });   } } 
like image 40
jewelsea Avatar answered Sep 20 '22 16:09

jewelsea