如何在JavaFX的TextField中强制进行双重输入? [英] How to force a double input in a TextField in JavaFX?

查看:118
本文介绍了如何在JavaFX的TextField中强制进行双重输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何确保用户在给定的TextField中仅输入双精度值?

我找到了解决方案整数 bu我无法将其用于双打.我应该写什么而不是"\\d*""[^\\d]"来使它适用于双打?

I found a solution for integers bu I can't manage to use it for doubles. What should I write instead of the "\\d*" and "[^\\d]" to make it work for doubles?

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

推荐答案

使用侦听器并在用户输入无效值时还原为有效值的方法是可行的,但是如果您使用其他侦听器,则可能会产生问题.文本字段的textProperty.这些侦听器将观察到无效值和有效值,因此他们必须知道要过滤掉所有无效值.

The approach of using a listener and reverting to valid values if invalid values are input by the user will work, but it can create issues if you have other listeners on the text field's textProperty. Those listeners will observe the invalid values as well as the valid ones, so they have to know to filter out any invalid values.

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

A better approach is to use a TextFormatter. The TextFormatter can do two things:

  1. 定义过滤器",该过滤器可以否决或修改对TextField文本所做的任何更改
  2. 定义一个转换器",它定义了如何根据您的情况在文本之间来回转换任何特定类型的值(例如Double).
  1. Define a "Filter", which can veto, or modify, any changes made to the TextField's text
  2. Define a "converter", which defines how to convert the text to and from values of any specific type (e.g. Double) in your case.

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

Defining the appropriate filter can be tricky: you want to allow any reasonable edits by the user. This means the text may be in an invalid state while the user is editing; e.g. you probably want to allow the text field to be completely empty, even though that does not represent a valid value. (Otherwise, it becomes annoying to the user if, for example, they want to change "1" to "2".) Similarly you probably want to allow things like "-" and ".", etc.

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

Here is an example. The filter should modify the change that is passed to it, if needed, and can return null to completely veto a change. This example simply checks if the text represents a valid editing state, and returns the change unmodified if it does, vetoing it otherwise. The formatter needs to deal with any text that is allowed by the filter and convert it to a double. Here anything that is incomplete is just represented as zero.

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);

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

You can make the regular expression more complex if needed, e.g. to support grouping characters ("1,000.0"), localization ("1.003,14159" if that is appropriate for the locale), or scientific-notation-like representations ("6.022E23", etc), and to enforce minimum or maximum values, etc. You can even do things such as modifying the change, so that if the user types a - anywhere in the text, it just flips the sign of the number. (Refer to the TextFormatter.Change documentation for that kind of functionality.)

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

Note you can get and set the double value (as provided by the converter) directly from the formatter, which has an ObjectProperty<Double> valueProperty(). So you can do things like

// 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());
});

这是SSCCE.第二个文本字段就在那里,因此您可以看到将焦点移到另一个控件上的效果(如果值已更改,它将提交"值并在文本格式化程序上调用侦听器;如果用户更改了类似的内容,按Enter键.

Here is a SSCCE. The second text field is just there so that you can see the effect of moving focus to a different control (it "commits" the value and invokes the listener on the text formatter, if the value has changed; a similar thing happens if the user presses enter).

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);
    }

}

这篇关于如何在JavaFX的TextField中强制进行双重输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆