如何限制TextField,使其只能包含一个'';性格JavaFX

如何限制TextField,使其只能包含一个'';性格JavaFX,java,regex,javafx,textfield,Java,Regex,Javafx,Textfield,在互联网上,我发现了非常有用的类,使用它我可以限制文本字段。我遇到一个问题,我的文本字段只能包含一个“.”字符。我怀疑我可以通过编写适当的正则表达式并将其设置为对该类实例的限制来处理这个问题。我使用下面的正则表达式:“[0-9.-]”,但它允许用户输入尽可能多的点。请您帮助我配置文本字段,以便不允许超过一个“.” import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProp

在互联网上,我发现了非常有用的类,使用它我可以限制文本字段。我遇到一个问题,我的文本字段只能包含一个“.”字符。我怀疑我可以通过编写适当的正则表达式并将其设置为对该类实例的限制来处理这个问题。我使用下面的正则表达式:“[0-9.-]”,但它允许用户输入尽可能多的点。请您帮助我配置文本字段,以便不允许超过一个“.”

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);
}
导入javafx.beans.property.IntegerProperty;
导入javafx.beans.property.SimpleIntegerProperty;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.scene.control.TextField;
/**
*安东于2015年7月14日创作。
*/
公共类RestrictiveTextField扩展了TextField{
private IntegerProperty maxLength=新的SimpleIntegerProperty(这个“maxLength”,-1);
private StringProperty restrict=新的SimpleStringProperty(此“限制”);
公共限制文本字段(){
超级(“0”);
textProperty().addListener(新的ChangeListener()){
私有布尔忽略;
@凌驾

public void changed(observeValue您可以使用以下正则表达式

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

或者正如VGR所指出的,“句点在字符类括号内没有特殊意义,0或1时间可以用“?”(问号)表示。”,因此您也可以使用

"[^.]*\\.?[^.]"
我不知道为什么,但是您的类似乎在正则表达式中附加了一个
*
,因此上面的正则表达式实际上会

"[^\\.]*\\.{0,1}[^\\.]*"
也就是说

  • 它将允许除
    以外的任何字符0次或更多次(贪婪)
  • 它将允许
    0或1次
  • 它将允许除
    以外的任何字符0次或更多次(贪婪)
  • 这就是你似乎需要的


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

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

    所以你可能想要像这样的东西

    可选减号,后跟任意位数或至少一位数、句点(
    )和任意位数

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

    要将其与
    文本字段
    一起使用,推荐的方法是使用。
    文本格式化程序
    由两部分组成:一个转换器,用于在文本和它所表示的值之间进行转换(在您的情况下,一个
    Double
    可以使用内置的
    DoubleStringConverter
    ),反之亦然,然后是一个筛选器。该筛选器作为一个函数实现,该函数接受
    TextFormatter.Change
    对象并返回相同类型的对象。通常,您可以保持
    Change
    对象的原样并返回它(接受
    更改
    “原样”),或者以某种方式修改它。返回
    null
    表示“无更改”也是合法的。因此,在这里的简单示例中,只需检查新建议的文本,看看它是否与正则表达式匹配,如果匹配,则按原样返回更改,否则返回
    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);
        }
    }
    
    import java.util.regex.Pattern;
    导入javafx.application.application;
    导入javafx.geometry.Insets;
    导入javafx.scene.scene;
    导入javafx.scene.control.TextField;
    导入javafx.scene.control.TextFormatter;
    导入javafx.scene.layout.StackPane;
    导入javafx.stage.stage;
    导入javafx.util.converter.DoubleStringConverter;
    公共类NumericTextFieldExample扩展了应用程序{
    @凌驾
    公共无效开始(阶段primaryStage){
    TextField TextField=新的TextField();
    Pattern validDoubleText=Pattern.compile(“-?(\\d*))|(\\d+\\.\\d*)”;
    TextFormatter TextFormatter=新的TextFormatter(新的DoubleStringConverter(),0.0,
    更改->{
    字符串newText=change.getControlNewText();
    if(validDupleText.matcher(newText.matches()){
    回报变化;
    }否则返回null;
    });
    setTextFormatter(textFormatter);
    textFormatter.valueProperty().addListener((obs、oldValue、newValue)->{
    System.out.println(“新双值”+新值);
    });
    StackPane root=新的StackPane(textField);
    根。设置填充(新插图(24));
    primaryStage.setScene(新场景(根));
    primaryStage.show();
    }
    公共静态void main(字符串[]args){
    发射(args);
    }
    }
    
    请提供有效和无效输入的示例。句点在字符类括号内没有特殊含义,因此您可以将其缩短为“[^.]*\\?[^.]*”
    。非常感谢!你能帮我写一个处理这个字符串的正则表达式吗:1858653333.9876767谢谢你的及时详尽的回答!现在我知道使用TextFormatter更好了。你能再帮我一次吗:如果TextField文本的格式必须是:“-302855453645992.06458”或指数形式?如何正确地将文本形式字段转换为BigDecimal,反之亦然?是:您需要修改正则表达式以允许逗号,并且需要编写自己的
    StringConverter
    实现和
    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);
        }
    }