如何在JavaFX中的TextField中强制双输入?

Rob*_*bb1 3 java javafx input textfield

如何确保用户只在给定的TextField中输入双值

我找到了一个整数解决方案,我无法将其用于双打.我应该怎么写,而不是"\\d*""[^\\d]"使其双打工作?

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]", ""));
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 6

如果用户输入了无效值,则使用侦听器并恢复有效值的方法将起作用,但如果在文本字段上有其他侦听器,则会产生问题textProperty.那些听众将观察无效值以及有效值,因此他们必须知道过滤掉任何无效值.

更好的方法是使用a TextFormatter.该TextFormatter可以做两件事情:

  1. 定义一个"过滤器",它可以否决或修改对TextField文本所做的任何更改
  2. 定义一个"转换器",它定义如何Double在您的情况下将文本转换为任何特定类型(例如)的值.

定义适当的过滤器可能很棘手:您希望允许用户进行任何合理的编辑.这意味着在用户编辑时文本可能处于无效状态; 例如,您可能希望允许文本字段完全为空,即使它不表示有效值.(否则,如果用户想要将"1"更改为"2",则会对用户造成烦恼.)同样,您可能希望允许" - "和"."等内容.

这是一个例子.如果需要,过滤器应修改传递给它的更改,并且可以返回null完全否决更改.此示例仅检查文本是否表示有效的编辑状态,如果更改则返回未修改的更改,否则将否决它.格式化程序需要处理过滤器允许的任何文本并将其转换为double.这里任何不完整的东西都只表示为零.

Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");

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) || "-.".equals(s)) {
            return 0.0 ;
        } else {
            return Double.valueOf(s);
        }
    }


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

TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
TextField textField = new TextField();
textField.setTextFormatter(textFormatter);
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以使正则表达式更复杂,例如,支持分组字符("1,000.0"),本地化("1.003,14159"如果适用于语言环境),或类似科学表示法("6.022E23"等),并强制执行最小值或最大值,您甚至可以执行诸如修改更改之类的操作,这样,如果用户-在文本中的任何位置键入内容,它只会翻转数字的符号.(有关此类功能,请参阅TextFormatter.Change文档.)

请注意,您可以直接从格式化程序获取并设置double值(由转换器提供),格式化程序具有ObjectProperty<Double> valueProperty().所以你可以做的事情

// update text field:
double value = ... ;
textFormatter.setValue(value);

// listen for changes in double value represented in text field
// Listener will be invoked when the user commits an edit:

textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
    System.out.println("User entered value: "+newValue.doubleValue());
});
Run Code Online (Sandbox Code Playgroud)

这是一个SSCCE.第二个文本字段就在那里,以便您可以看到将焦点移动到另一个控件的效果(它"提交"值并在文本格式化程序上调用侦听器,如果值已更改;如果用户发生类似的事情按下进入).

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.stage.Stage;
import javafx.util.StringConverter;

public class NumericTextField extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");

        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) || "-.".equals(s)) {
                    return 0.0 ;
                } else {
                    return Double.valueOf(s);
                }
            }


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

        TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
        TextField textField = new TextField();
        textField.setTextFormatter(textFormatter);

        textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
            System.out.println("User entered value: "+newValue.doubleValue());
        });

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

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

}
Run Code Online (Sandbox Code Playgroud)