在 JavaFX 数字 TextField 中处理无穷大

Handling Infinity in JavaFX numerical TextField

我有一个 JavaFX TextField 专门用于接受数字,包括科学记数法。它几乎可以做我想做的一切。但是,因为它接受科学计数法,所以用户很容易输入超出 double 可以表示的范围的数字。当他们这样做时,TextField 显示“Infinity”(或“-Infinity”)。发生这种情况时,无法再编辑该字段来更正问题。也不能选择和删除内容。点击“Escape”键不会return到之前的内容。

这是一个 SSCCE,它与几年前 by James_D to this 密切相关。

import java.text.DecimalFormatSymbols;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.StringConverter;

public class NumericTextFieldDemo extends Application {

    char sep = new DecimalFormatSymbols().getDecimalSeparator();
    String negStarter = new StringBuilder("-").append(sep).toString();
    String posStarter = new StringBuilder("+").append(sep).toString();
    String patternStr = new StringBuilder()
            .append("[+|-]?(([1-9][0-9]*)|0)?(\")
            .append(sep)
            .append("[0-9]*)?(([e|E][+|-]?[0-9]*)?)")
            .toString();
    Pattern validEditingState = Pattern.compile(patternStr);

    class NumericTextField extends TextField {

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

        StringConverter<Double> converter = new StringConverter<Double>() {

            @Override
            public Double fromString(String s) {
                if (s.isEmpty() || "-".equals(s) || "+".equals(s)
                        || negStarter.equals(s) || posStarter.equals(s)) {
                    return 0.0;
                } else {
                    return Double.valueOf(s);
                }
            }

            @Override
            public String toString(Double d) {
                return d.toString();
            }
        };

        NumericTextField(double initValue) {
            TextFormatter<Double> textFormatter = new TextFormatter<>(converter, initValue, filter);
            textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
                System.out.println("User entered value: " + newValue);
            });
            setTextFormatter(textFormatter);
        }

        NumericTextField() {
            this(0.0);
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        NumericTextField ntf = new NumericTextField();
        // Setting the font seems to be required on macOS.
        ntf.setFont(new Font("Arial", 14));

        VBox root = new VBox(5, ntf);
        root.setAlignment(Pos.CENTER);
        primaryStage.setScene(new Scene(root, 250, 150));
        primaryStage.show();
    }

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

有什么方法可以捕获无穷大并使 TextField 处于可用状态吗?是否可以对 class 进行一些更改以防止首先输入此类数字?

只需为双打使用内置的字符串转换器:

    TextFormatter<Double> tf = new TextFormatter<>(new DoubleStringConverter());
    TextField ntf = new TextField();
    ntf.setTextFormatter(tf);