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

时间:2015-07-16 15:15:43

标签: java regex javafx textfield

在互联网上,我发现了非常有用的类,使用它我可以限制TextField。我遇到了一个问题,我的TextField只能包含一个'。'字符。我怀疑我可以通过编写appripriate正则表达式并将其设置为对该类实例的限制来处理此问题。我使用以下正则表达式:“[0-9.-]”,但它允许与用户类型一样多的点。我可以请你帮我配置我的TextField,使其不超过一个'。'是允许的。

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

}

3 个答案:

答案 0 :(得分:9)

正则表达式有各种版本,具体取决于您想要支持的内容。请注意,您不仅希望匹配有效数字,还要匹配部分条目,因为用户必须能够对其进行编辑。因此,例如,空字符串不是有效数字,但您当然希望用户能够在编辑时删除其中的所有内容;同样,您希望允许"0."等。

所以你可能想要像

这样的东西

可选减号,然后 任意数量的数字,至少一位数,句号(.)和任意位数。

这方面的正则表达式可能是-?((\\d*)|(\\d+\.\\d*))。可能有其他方法可以做到这一点,其中一些可能更有效。如果你想支持指数形式("1.3e12"),它会变得更复杂。

要将其与TextField一起使用,建议的方法是使用TextFormatterTextFormatter包含两件事:一个转换器,用于在文本及其代表的值之间进行转换(在您的情况下为Double:您可以使用内置的DoubleStringConverter),以及反之亦然,然后是过滤器。过滤器实现为一个函数,它接受TextFormatter.Change对象并返回相同类型的对象。通常,您要保留Change对象,然后将其返回(接受Change&#34;按原样#34;),或者以某种方式修改它。返回null代表&#34;无变化&#34;也是合法的。所以在这里简单的情况下,只需检查新建议的文本,看它是否与正则表达式匹配,返回更改&#34;按原样#34;如果匹配则返回null

示例:

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

答案 1 :(得分:1)

您可以使用以下正则表达式

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

或者正如VGR指出的那样,“一个句点在字符类括号内没有特殊含义,0或1时间可以用'?'表示(问号)。“,所以你也可以使用,

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

我不知道为什么但是你的班级似乎在正则表达式附加*,所以上面的正则表达式会有效地变成,

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

这意味着,

  1. 除了. 0次或以上(贪婪)之外,它将允许任何字符。
  2. 允许. 0或1次。
  3. 除了. 0次或以上(贪婪)之外,它将允许任何字符。
  4. 这是你似乎需要的。 DEMO

答案 2 :(得分:0)

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

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