简体   繁体   English

如何限制TextField,使其只能包含一个'。' 字符? JavaFX的

[英]How to restrict TextField so that it can contain only one '.' character? JavaFX

On the Internet, I found very useful class, using which I can restrict TextField. 在Internet上,我发现了非常有用的类,使用它我可以限制TextField。 I encountered a problem, where my TextField can contain only one '.' 我遇到了一个问题,我的TextField只能包含一个'。' character. 字符。 I suspect that I can handle this by writing an appripriate regex and set it as a restriction on the instance of that class. 我怀疑我可以通过编写appripriate正则表达式并将其设置为对该类实例的限制来处理此问题。 I use the following regex: "[0-9.-]", but it allows as many dots as the user types. 我使用以下正则表达式:“[0-9.-]”,但它允许与用户类型一样多的点。 May I ask you to help me to configure my TextField so that no more than one '.' 我可以请你帮我配置我的TextField,使其不超过一个'。' is allowed. 被允许。

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;

/**
 * Created by Anton on 7/14/2015.
 */
public class RestrictiveTextField extends TextField {
private IntegerProperty maxLength = new SimpleIntegerProperty(this, "maxLength", -1);
private StringProperty restrict = new SimpleStringProperty(this, "restrict");

public RestrictiveTextField() {
    super("0");
    textProperty().addListener(new ChangeListener<String>() {

        private boolean ignore;

        @Override
        public void changed(ObservableValue<? extends String> observableValue, String s, String s1) {

            if (ignore || s1 == null)
                return;
            if (maxLength.get() > -1 && s1.length() > maxLength.get()) {
                ignore = true;
                setText(s1.substring(0, maxLength.get()));
                ignore = false;
            }

            if (restrict.get() != null && !restrict.get().equals("") && !s1.matches(restrict.get() + "*")) {
                ignore = true;
                setText(s);
                ignore = false;
            }
        }
    });
}

/**
 * The max length property.
 *
 * @return The max length property.
 */
public IntegerProperty maxLengthProperty() {
    return maxLength;
}

/**
 * Gets the max length of the text field.
 *
 * @return The max length.
 */
public int getMaxLength() {
    return maxLength.get();
}

/**
 * Sets the max length of the text field.
 *
 * @param maxLength The max length.
 */
public void setMaxLength(int maxLength) {
    this.maxLength.set(maxLength);
}

/**
 * The restrict property.
 *
 * @return The restrict property.
 */
public StringProperty restrictProperty() {
    return restrict;
}

/**
 * Gets a regular expression character class which restricts the user input.

 *
 * @return The regular expression.
 * @see #getRestrict()
 */
public String getRestrict() {
    return restrict.get();
}

/**
 * Sets a regular expression character class which restricts the user input.

 * E.g. [0-9] only allows numeric values.
 *
 * @param restrict The regular expression.
 */
public void setRestrict(String restrict) {
    this.restrict.set(restrict);
}

} }

There are various versions of the regex, depending on exactly what you want to support. 正则表达式有各种版本,具体取决于您想要支持的内容。 Note that you don't only want to match valid numbers, but also partial entries, because the user has to be able to edit this. 请注意,您不仅要匹配有效数字,还要匹配部分条目,因为用户必须能够编辑它。 So, for example, an empty string is not a valid number, but you certainly want the user to be able to delete everything that's there while they are editing; 因此,例如,空字符串不是有效数字,但您当然希望用户能够删除编辑时那里的所有内容; similarly you want to allow "0." 同样你想要允许"0." , etc.

So you probably want something like 所以你可能想要类似的东西

Optional minus sign, followed by either any number of digits, or at least one digit, a period ( . ), and any number of digits. 可选的减号,接着为无论任何数量的数字, 至少一个数字,句点( . )和任何数量的数字。

The regex for this could be -?((\\\\d*)|(\\\\d+\\.\\\\d*)) . 这个的正则表达式可能是-?((\\\\d*)|(\\\\d+\\.\\\\d*)) There are probably other ways to do this, some of them perhaps more efficient. 可能有其他方法可以做到这一点,其中一些可能更有效。 And if you want to support exponential forms ( "1.3e12" ) it gets more complex. 如果你想支持指数形式( "1.3e12" ),它会变得更复杂。

To use this with a TextField , the recommended way is to use a TextFormatter . 要将其与TextField一起使用,建议的方法是使用TextFormatter The TextFormatter consists of two things: a converter to convert between the text and the value it represents (a Double in your case: you can just use the built-in DoubleStringConverter ), and vice versa, and then a filter. TextFormatter由两部分组成:一个转换器,用于在文本和它所代表的值之间进行转换(在你的情况下是一个Double :你可以只使用内置的DoubleStringConverter ),反之亦然,然后是一个过滤器。 The filter is implemented as a function that takes a TextFormatter.Change object and returns an object of the same type. 过滤器实现为一个函数,它接受TextFormatter.Change对象并返回相同类型的对象。 Typically you either leave the Change object as it is and return it (to accept the Change "as is"), or modify it somehow. 通常,您可以保留Change对象并将其返回(以“按原样”接受Change ),或者以某种方式对其进行修改。 It is also legal to return null to represent "no change". 返回null表示“无变化”也是合法的。 So in your simple case here, just examine the new proposed text, see if it matches the regular expression, return the change "as is" if it matches and return null otherwise. 所以在这里简单的情况下,只需检查新建议的文本,看它是否与正则表达式匹配,如果匹配则返回“原样”,否则返回null

Example: 例:

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.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.converter.DoubleStringConverter;

public class NumericTextFieldExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextField textField = new TextField();

        Pattern validDoubleText = Pattern.compile("-?((\\d*)|(\\d+\\.\\d*))");

        TextFormatter<Double> textFormatter = new TextFormatter<Double>(new DoubleStringConverter(), 0.0, 
            change -> {
                String newText = change.getControlNewText() ;
                if (validDoubleText.matcher(newText).matches()) {
                    return change ;
                } else return null ;
            });

        textField.setTextFormatter(textFormatter);

        textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> {
            System.out.println("New double value "+newValue);
        });

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

You can use the following regex, 你可以使用以下正则表达式,

"[^\\.]*\\.{0,1}[^\\.]"

Or as VGR has pointed out, "A period has no special meaning inside character class brackets and 0 or 1 time can be represented with a '?' 或者正如VGR所指出的那样, “一个句点在字符类括号内没有特殊含义,0或1时间可以用'?'表示 (question mark)." (问号)。” , so you can also use, ,所以你也可以使用,

"[^.]*\\.?[^.]"

I don't know why but your class seems to append a * to the regex, so the above regex will effectively become, 我不知道为什么但是你的班级似乎在正则表达式上添加* ,所以上面的正则表达式会有效地成为,

"[^\\.]*\\.{0,1}[^\\.]*"

Which means, 意思是,

  1. It will allow any character except a . 除了a之外,它将允许任何字符. 0 or more times (greedy). 0次或更多次(贪心)。
  2. It will allow a . 它会允许一个. 0 or 1 times. 0或1次。
  3. It will allow any character except a . 除了a之外,它将允许任何字符. 0 or more times (greedy). 0次或更多次(贪心)。

This is what you seem to be needing. 这就是你似乎需要的东西。 DEMO DEMO

{[0-9]+\\.[0-9]+}

匹配任何数字,如果这实际上是你想要做的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM