【问题标题】:JavaFX Input Validation TextfieldJavaFX 输入验证文本字段
【发布时间】:2015-06-19 09:59:28
【问题描述】:

我正在使用 JavaFX 和 Scene Builder,并且我有一个带有文本字段的表单。其中三个文本字段从字符串解析为双精度。

我希望它们是学校分数,所以它们应该只允许在 1.0 到 6.0 之间。不应允许用户写“2.34.4”之类的东西,但可以写“5.5”或“2.9”之类的东西。

对已解析字段的验证:

public void validate(KeyEvent event) {
    String content = event.getCharacter();
    if ("123456.".contains(content)) {
            // No numbers smaller than 1.0 or bigger than 6.0 - How?
    } else {
        event.consume();
    }
}

如何测试用户输入的值是否正确?

我已经在 Stackoverflow 和 Google 上进行了搜索,但没有找到令人满意的解决方案。

【问题讨论】:

    标签: java javafx


    【解决方案1】:
    textField.focusedProperty().addListener((arg0, oldValue, newValue) -> {
            if (!newValue) { //when focus lost
                if(!textField.getText().matches("[1-5]\\.[0-9]|6\\.0")){
                    //when it not matches the pattern (1.0 - 6.0)
                    //set the textField empty
                    textField.setText("");
                }
            }
    
        });
    

    您也可以将模式更改为[1-5](\.[0-9]){0,1}|6(.0){0,1},然后1,2,3,4,5,6也可以(不仅是1.0,2.0,...)

    更新 这是一个允许值 1(.00) 到 6(.00) 的小型测试应用程序:

    public class JavaFxSample extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Enter number and hit the button");
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        Label label1To6 = new Label("1.0-6.0:");
        grid.add(label1To6, 0, 1);
        TextField textField1To6 = new TextField();
    
        textField1To6.focusedProperty().addListener((arg0, oldValue, newValue) -> {
            if (!newValue) { // when focus lost
                    if (!textField1To6.getText().matches("[1-5](\\.[0-9]{1,2}){0,1}|6(\\.0{1,2}){0,1}")) {
                        // when it not matches the pattern (1.0 - 6.0)
                        // set the textField empty
                        textField1To6.setText("");
                    }
                }
            });
        grid.add(textField1To6, 1, 1);
        grid.add(new Button("Hit me!"), 2, 1);
        Scene scene = new Scene(grid, 300, 275);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    
    }
    

    【讨论】:

    • 非常感谢@griFlo,但仍然存在问题。我无法输入像 "5.0", "4.7", "2.8" 或 "1.9" 这样的值。你知道我怎么能告诉程序只有两位小数吗?
    • @BRsmover 你说的所有值都应该被允许(事实上,我只是用上面的代码测试了它,它只是找到了)。两位小数是什么意思?您可以将这个正则表达式用于[1-5](\.[0-9]{1,2}){0,1}|6(.0{1,2}){0,1}(如果我理解正确的话)
    • 对不起,我一定是误会了什么……一切都很好!非常感谢!
    【解决方案2】:

    我不建议您为此使用 KeyEvent。

    您应该使用更经典的方式,例如在用户完成填写文本字段或单击保存按钮时验证用户输入。

    /**
     * Called this when the user clicks on the save button or finish to fill the text field.
     */
    private void handleSave() {
            // If the inputs are valid we save the data
            if(isInputValid()){
                note=(DOUBLE.parseDouble(textField.getText()));
            }else // do something such as notify the user and empty the field
    }
    
    /**
     * Validates the user input in the text fields.
     * 
     * @return true if the input is valid
     */
    private boolean isInputValid() {
        Boolean b= false;
        if (!(textField.getText() == null || textFiled.getText().length() == 0)) {
            try {
                // Do all the validation you need here such as
                Double d = Double.parseInt(textFiled.getText());
                if ( 1.0<d<6.0){
                    b=true;
                }
            } catch (NumberFormatException e) { 
            }
        return b;
    }
    

    【讨论】:

    • 我会详细说明这一点。我会调用验证方法 3 次:保存操作、文本字段的操作事件和失去焦点。通过这种方式,用户可以在出现错误时立即做出响应,同时防止保存不良数据。
    【解决方案3】:

    您可以使用 TextFormatter 防止非法输入:

    final Pattern pattern = Pattern.compile("(6\\.0)|([1-5]\\.[0-9])");
    textField.setTextFormatter(new TextFormatter<>(new DoubleStringConverter(), 0.0, change -> {
            final Matcher matcher = pattern.matcher(change.getControlNewText());
            return (matcher.matches() || matcher.hitEnd()) ? change : null;
    }));
    

    【讨论】:

    • 这不起作用。它将文本锁定为“0.0”,并防止对其进行任何更改。甚至光标也不能从文本末尾移动。
    【解决方案4】:

    如果您可以使用第三方库:

    已在此处回答了类似的问题:Form validator message 。

    对于您的情况,您可以选择 RegexValidator 来检查文本字段输入,并传递您从之前的答案中得到的正则表达式:

        JFXTextField validationField = new JFXTextField();
        validationField.setPromptText("decimal between 1.0 and 6.0");
        RegexValidator validator = new RegexValidator();
        validator.setRegexPattern("[1-5](\\.[0-9]{1,2}){0,1}|6(\\.0{1,2}){0,1}");
        validator.setMessage("Please enter proper value");
        validationField.getValidators().add(validator);
        validationField.focusedProperty().addListener((observable, oldValue, newValue) -> {
            if(!newValue)
                    validationField.validate();
        });
    

    【讨论】:

      【解决方案5】:

      如果需要,您可以创建一个执行输入验证的自定义 TextField。

      import java.awt.Toolkit;
      
      import javafx.event.EventHandler;
      import javafx.scene.control.TextField;
      import javafx.scene.control.TextInputControl;
      import javafx.scene.input.KeyEvent;
      
      /**
       * A text field that limits the user to certain number of characters and
       * prevents the user from typing certain characters
       * 
       * 
       */
      
      public class CustomTextField extends TextField
      {
          /**
           * The maximum number of characters this text field will allow
           * */
          private int maxNumOfCharacters;
          /**
           * A regular expression of characters that this text field does not allow
           * */
          private String unallowedCharactersRegEx;
      
          /*
           * If no max number of characters is specified the default value is set
           * */
          private static final int DEFAULT_MAX_NUM_OF_CHARACTERS = 1000;
      
          public CustomTextField()
          {
              maxNumOfCharacters = DEFAULT_MAX_NUM_OF_CHARACTERS;
              
              this.setOnKeyTyped(new EventHandler<KeyEvent>() {
                  public void handle(KeyEvent event)
                  {
                      // get the typed character
                      String characterString = event.getCharacter();
                      char c = characterString.charAt(0);
                      // if it is a control character or it is undefined, ignore it
                      if (Character.isISOControl(c) || characterString.contentEquals(KeyEvent.CHAR_UNDEFINED))
                          return;
      
                      // get the text field/area that triggered this key event and its text
                      TextInputControl source = (TextInputControl) event.getSource();
                      String text = source.getText();
      
                      // If the text exceeds its max length or if a character that matches
                      // notAllowedCharactersRegEx is typed
                      if (text.length() > maxNumOfCharacters
                              || (unallowedCharactersRegEx != null && characterString.matches(unallowedCharactersRegEx)))
                      {
                          // remove the last character
                          source.deletePreviousChar();
                          // make a beep sound effect
                          Toolkit.getDefaultToolkit().beep();
                      }
      
                  }
      
              });
      
          }
      
          public int getMaxNumOfCharacters()
          {
              return maxNumOfCharacters;
          }
      
          public void setMaxNumOfCharacters(int maxNumOfCharacters)
          {
              this.maxNumOfCharacters = maxNumOfCharacters;
          }
      
          public String getUnallowedCharactersRegEx()
          {
              return unallowedCharactersRegEx;
          }
      
          public void setUnallowedCharactersRegEx(String notAllowedRegEx)
          {
              this.unallowedCharactersRegEx = notAllowedRegEx;
          }
      
      }
      

      【讨论】:

      • 不,这是不完整的,因为它不会通过粘贴捕获无效输入,f.i. - 自 fx8u40 以来,textFormatter 是要走的路
      猜你喜欢
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多