add listener for javafx textField upto 2 decimal p

2019-02-18 17:53发布

问题:

I want to set javaFX text field upto two decimal places . I found the answer but it is for numeric value . e-g

 // 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]", ""));
        }
    }
});

In above code, what is replacement for limit value upto two decimal. Or is there any other solution for limit the textField. I have Binding TextField Here is My partial Code ...

  @FXML public TextField InvoiceTotal;

 private DoubleProperty invTotal;
 invTotal = new SimpleDoubleProperty(0);

 netAmount.bind(grossAmount.subtract(disc));

 StringConverter<? extends Number> converter= new DoubleStringConverter();

 Bindings.bindBidirectional(InvoiceTotal.textProperty(),invTotal,(StringConverter<Number>)converter);

Now I want to set two decimal limitation on InvoiceTotal textfield

回答1:

Use a text formatter on the text field. The pattern just has to match any possible decimal value with up to two decimal places. (Something like optional negative sign, followed by any number of digits, then optionally followed by a decimal point and 0-2 digits.) Just have the text formatter accept changes if the resulting text matches that pattern, and reject them otherwise.

import java.util.function.UnaryOperator;
import java.util.regex.Pattern;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class DecimalTextField extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pattern decimalPattern = Pattern.compile("-?\\d*(\\.\\d{0,2})?");

        UnaryOperator<Change> filter = c -> {
            if (decimalPattern.matcher(c.getControlNewText()).matches()) {
                return c ;
            } else {
                return null ;
            }
        };

        TextFormatter<Double> formatter = new TextFormatter<>(filter);

        TextField textField = new TextField();
        textField.setTextFormatter(formatter);
        StackPane root = new StackPane(textField);
        root.setPadding(new Insets(24));

        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}


回答2:

I couldn't resist. This is aboves answer in two lines (the ones that do all the work)

private static TextFormatter<Double> new3DecimalFormatter(){
        Pattern decimalPattern = Pattern.compile("-?\\d*(\\.\\d{0,3})?");
        return new TextFormatter<>(c -> (decimalPattern.matcher(c.getControlNewText()).matches()) ? c : null );
}