Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaFX中强制在文本字段中进行双重输入?_Java_Javafx_Input_Textfield - Fatal编程技术网

如何在JavaFX中强制在文本字段中进行双重输入?

如何在JavaFX中强制在文本字段中进行双重输入?,java,javafx,input,textfield,Java,Javafx,Input,Textfield,如何确保用户在给定的文本字段中只输入两个值 我找到了一个bu,我不能用它来打双打。我应该写什么来代替“\\d*”和“[^\\d]”,以使其适用于双打 textField.textProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> observable, String oldV

如何确保用户在给定的文本字段中只输入两个值

我找到了一个bu,我不能用它来打双打。我应该写什么来代替
“\\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]", ""));
        }
    }
});
textField.textProperty().addListener(新的ChangeListener()){
@凌驾

public void changed(observeValue您可以使用Double.parseDouble。这将为您进行解析,而不是编写自己的双重验证。然后您可以检查数字格式异常或空指针异常

    try
    {
        Double.parseDouble(newValue);
        // Valid double
    }
    catch (NullPointerException | NumberFormatException ex)
    {
        // Not valid double
    }

您可以在双精度上使用java正则表达式,并将非数字字符替换为数字。在中,您必须指定整数部分允许的位数,例如1,10

textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        if (!newValue.matches("[0-9]{<range>}(\\.[0-9]*)?")) {
            textField.setText(newValue.replaceAll("[^\\d.]", ""));
            StringBuilder aus = new StringBuilder(newValue);
            boolean firstPointFound = false;
            for (int i = 0; i < aus.length(); i++){
                if(aus.charAt(i) == '.') {
                    if(!firstPointFound)
                        firstPointFound = true;
                    else
                        aus.deleteCharAt(i);
                }
            }
            newValue = aus.toString();
        }
    }
});
textField.textProperty().addListener(新的ChangeListener()){
@凌驾

更改公众假期(ObservalEvalue如果用户输入了无效值,则使用侦听器并恢复为有效值的方法将起作用,但如果文本字段的
textProperty
上有其他侦听器,则可能会产生问题。这些侦听器将观察无效值和有效值,因此他们必须知道如何过滤掉任何输入有效值

更好的方法是使用。
TextFormatter
可以做两件事:

  • 定义一个“过滤器”,它可以否决或修改对
    文本字段
    文本所做的任何更改
  • 定义一个“转换器”,它定义了在您的案例中如何将文本转换为任何特定类型的值(例如,
    Double
  • 定义适当的筛选器可能很棘手:您希望允许用户进行任何合理的编辑。这意味着在用户编辑时文本可能处于无效状态;例如,您可能希望允许文本字段完全为空,即使这并不表示有效值。(否则,例如,如果用户希望将“1”更改为“2”,则会让用户感到恼火。)类似地,您可能希望允许“-”和“.”等内容

    下面是一个示例。如果需要,筛选器应该修改传递给它的更改,并且可以返回
    null
    以完全否决更改。此示例仅检查文本是否表示有效的编辑状态,如果表示有效的编辑状态,则返回未经修改的更改,否则将予以否决。格式化程序需要处理所有允许的文本wed被过滤器连接并将其转换为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);
    
    这是一个SSCCE。第二个文本字段就在那里,以便您可以看到将焦点移动到其他控件的效果(如果值已更改,它“提交”该值并调用文本格式化程序上的侦听器;如果用户按enter键,则会发生类似的情况)

    import java.util.function.UnaryOperator;
    导入java.util.regex.Pattern;
    导入javafx.application.application;
    导入javafx.beans.value.observeValue;
    导入javafx.geometry.Pos;
    导入javafx.scene.scene;
    导入javafx.scene.control.TextField;
    导入javafx.scene.control.TextFormatter;
    导入javafx.scene.layout.VBox;
    导入javafx.stage.stage;
    导入javafx.util.StringConverter;
    公共类NumericTextField扩展了应用程序{
    @凌驾
    public void start(Stage primaryStage)引发异常{
    Pattern validitingstate=Pattern.compile(“-?([1-9][0-9]*)0)?(\\\[0-9]*)?”;
    一元运算符筛选器=c->{
    String text=c.getControlNewText();
    if(validEditingState.matcher(text.matches()){
    返回c;
    }否则{
    返回null;
    }
    };
    StringConverter转换器=新的StringConverter(){
    @凌驾
    公共双fromString(字符串s){
    如果(s.isEmpty()| |“-”。等于(s)| |。”。等于(s)| |“-。。等于(s)){
    返回0.0;
    }否则{
    返回两倍。值为;
    }
    }
    @凌驾
    公共字符串到字符串(双d){
    返回d.toString();
    }
    };
    TextFormatter TextFormatter=新的TextFormatter(转换器,0.0,过滤器);
    TextField TextField=新的TextField();
    setTextFormatter(textFormatter);
    
    textFormatter.valueProperty().addListener((Observalevalue感谢您的回答,但是如果我尝试输入
    99.99。
    在第二次
    时,我会收到一个错误(而且输入更改为
    9999
    )。你知道如何解决这个问题吗?谢谢你的回答,但我正在尝试强制用户只输入双精度值。我希望避免管理无效输入。强制用户输入双精度值的唯一方法是检测无效输入。对正则表达式匹配执行if或将上述代码拉入测试之间没有区别返回true或false的Double方法。“强制用户输入Double的唯一方法是检测无效的输入。”不正确。例如,您可以重写各种
    insert
    方法,或者使用
    TextFormatter
    。使用异常处理进行逻辑控制也是一种非常糟糕的做法。异常应该是针对异常情况,而不是您期望在正常事件运行中发生的情况。使用Double.parse与任何手动p一样糟糕模式匹配:无区域设置感知。至少,您必须在TextFormatter中使用NumberFormat…,正如@James_DDon所建议的那样,不要使用侦听器;text属性的其他观察者将在还原之前看到无效输入。请改为使用
    TextFormatter
    。不要进行任何手动模式匹配,它将在大多数非默认情况下中断-美国/英国地区。。
    // 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());
    });
    
    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);
        }
    
    }