【问题标题】:How to limit the amount of characters a javafx textfield如何限制 javafx 文本字段的字符数
【发布时间】:2014-03-28 13:29:04
【问题描述】:

我正在使用 FXML 来设置我的表单,但我需要设置文本字段中的字符限制。我怎样才能做到这一点?

【问题讨论】:

    标签: javafx fxml


    【解决方案1】:

    您不能直接设置字符数限制。但是您可以在文本字段的lengthProperty() 中添加listener

    import javafx.application.Application;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.scene.Scene;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class TextFieldLimit extends Application {
        private static final int LIMIT = 10;
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(final Stage primaryStage) {
    
            final TextField textField = new TextField();
            textField.lengthProperty().addListener(new ChangeListener<Number>() {
    
                @Override
                public void changed(ObservableValue<? extends Number> observable,
                        Number oldValue, Number newValue) {
                    if (newValue.intValue() > oldValue.intValue()) {
                        // Check if the new character is greater than LIMIT
                        if (textField.getText().length() >= LIMIT) {
    
                            // if it's 11th character then just setText to previous
                            // one
                            textField.setText(textField.getText().substring(0, LIMIT));
                        }
                    }
                }
            });
    
            VBox vbox = new VBox(20);
            vbox.getChildren().add(textField);
    
            Scene scene = new Scene(vbox, 400, 300);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    }
    

    【讨论】:

    • 我推荐textField.setText(textField.getText().substring(0, LIMIT));。否则,如果用户使用复制和粘贴在其中转储一个非常大的字符串,它将重复调用侦听器,一次减少一个字符。
    【解决方案2】:

    更优雅的解决方案

    Pattern pattern = Pattern.compile(".{0,25}");
        TextFormatter formatter = new TextFormatter((UnaryOperator<TextFormatter.Change>) change -> {
            return pattern.matcher(change.getControlNewText()).matches() ? change : null;
        });
    
        textField.setTextFormatter(formatter);
    

    其中 0 和 25 - 最小和最大字符数。 + 设置输入文本模式的能力

    【讨论】:

      【解决方案3】:

      这是我限制文本字段长度的解决方案。 我不会推荐使用侦听器(在 text 属性或 length 属性上)的解决方案,它们在所有情况下都不能正确运行(就我所见)。 我创建了一个最大长度的 HTML 输入文本,并将其与我在 JavaFX 中的文本字段进行比较。在这两种情况下,我对粘贴操作 (Ctrl + V)、取消操作 (Ctrl + Z) 的行为相同。这里的目标是在修改文本字段之前检查文本是否有效。 我们可以对数字文本字段使用类似的方法。

      import java.util.Objects;
      import javafx.beans.property.IntegerProperty;
      import javafx.beans.property.SimpleIntegerProperty;
      import javafx.scene.control.TextField;   
      
      public class LimitedTextField extends TextField {
      
          private final IntegerProperty maxLength;
      
          public LimitedTextField() {
              super();
              this.maxLength = new SimpleIntegerProperty(-1);
          }
      
          public IntegerProperty maxLengthProperty() {
              return this.maxLength;
          }
      
          public final Integer getMaxLength() {
              return this.maxLength.getValue();
          }
      
          public final void setMaxLength(Integer maxLength) {
              Objects.requireNonNull(maxLength, "Max length cannot be null, -1 for no limit");
              this.maxLength.setValue(maxLength);
          }
      
          @Override
          public void replaceText(int start, int end, String insertedText) {
              if (this.getMaxLength() <= 0) {
                  // Default behavior, in case of no max length
                  super.replaceText(start, end, insertedText);
              }
              else {
                  // Get the text in the textfield, before the user enters something
                  String currentText = this.getText() == null ? "" : this.getText();
      
                  // Compute the text that should normally be in the textfield now
                  String finalText = currentText.substring(0, start) + insertedText + currentText.substring(end);
      
                  // If the max length is not excedeed
                  int numberOfexceedingCharacters = finalText.length() - this.getMaxLength();
                  if (numberOfexceedingCharacters <= 0) {
                      // Normal behavior
                      super.replaceText(start, end, insertedText);
                  }
                  else {
                      // Otherwise, cut the the text that was going to be inserted
                      String cutInsertedText = insertedText.substring(
                              0, 
                              insertedText.length() - numberOfexceedingCharacters
                      );
      
                      // And replace this text
                      super.replaceText(start, end, cutInsertedText);
                  }
              }
          }
      }
      

      使用 JavaFX 8 和 Java 8u45 测试

      【讨论】:

        【解决方案4】:

        我使用一个简单的 ChangeListener 调用来测试执行停止的条件。

        textFild.addListener((observable, oldValue, newValue) -> {
            if (newValue.length() == MAX_SIZE) {
                textField.setText(oldValue);
            }
        });
        

        【讨论】:

          【解决方案5】:

          这是一个非常简单的解决方案,似乎对我有用。

          textfield.setOnKeyTyped(event ->{
                  int maxCharacters = 5;
                  if(tfInput.getText().length() > maxCharacters) event.consume();
              });
          

          【讨论】:

            【解决方案6】:

            这是一个行之有效的解决方案:

            @FXML
            void limitTextFields(KeyEvent event) {
                int maxLength = 5;
                TextField tf = (TextField) event.getSource();
                if (tf.getText().length() > maxLength) {
                    tf.deletePreviousChar();
                }
            }
            

            【讨论】:

            • 否(您只能限制直接输入,而不是粘贴 f.i.),请改用 textFormatter
            【解决方案7】:

            这是在通用文本字段上完成这项工作的更好方法:

            public static void addTextLimiter(final TextField tf, final int maxLength) {
                tf.textProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
                        if (tf.getText().length() > maxLength) {
                            String s = tf.getText().substring(0, maxLength);
                            tf.setText(s);
                        }
                    }
                });
            }
            

            完美运行,除了那个 Undo 错误。

            【讨论】:

              【解决方案8】:

              下面的 1-liner 可以做到这一点,而 5 是 TextField tf 的限制:

              tf.setTextFormatter(new TextFormatter<>(c -> c.getControlNewText().matches(".{0,5}") ? c : null));
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-01-21
                • 1970-01-01
                • 1970-01-01
                • 2018-04-09
                • 1970-01-01
                • 2020-03-27
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多