【问题标题】:How to format a text field javafx如何格式化文本字段javafx
【发布时间】:2016-02-10 06:21:41
【问题描述】:

我希望能够以 hh:mm:ss 格式在 javafx 文本字段中输入时间。我将如何格式化文本字段?我已经得到了正则表达式方法,所以它只接受数字作为输入:

public void format(TextField t, String regex){
    TextFormatter<String> formatter = new TextFormatter<String>( change -> {
        change.setText(change.getText().replaceAll(regex, ""));
        return change; 


    });
    t.setTextFormatter(formatter);
}

我还有一种方法可以限制文本字段中允许的字符数量:

public void limitLength(int maxLength, TextField t){
    t.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 (t.getText().length() >= maxLength) {

                    t.setText(t.getText().substring(0, maxLength));
                }
            }
        }
    });
}

但是,这些都不能帮助我获得我想要的时间格式。理想的情况是初始文本为 00:00:00,用户只能编辑数字,不能触摸冒号。如果我能够确保每个冒号之间有 2 位数字,那就太棒了,即用户应该无法在数字之间移动,例如 0:000:00。

感谢您的帮助。

【问题讨论】:

标签: regex javafx textfield text-formatting


【解决方案1】:

使用 SimpleDateFormat

已经有一个用于格式化日期的类,您可以将其与TextField's textFormatter 一起使用:SimpleDateFormat

TextField tf = new TextField();
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
tf.setTextFormatter(new TextFormatter<>(new DateTimeStringConverter(format), format.parse("00:00:00")));

有关字符含义的更详细说明,请参阅 SimpleDateFormat 的 javadoc。

使用 3 个不同的文本字段

您还可以使用 3 个不同的 TextFields 并删除背景和边框并将它们放入 HBox 以获得不可编辑的 :s:

TextField hours = new TextField();
TextField minutes = new TextField();
TextField seconds = new TextField();
StringConverter<Integer> minSecConverter = new IntRangeStringConverter(0, 59);
minutes.setTextFormatter(new TextFormatter<>(minSecConverter, 0));
seconds.setTextFormatter(new TextFormatter<>(minSecConverter, 0));
hours.setTextFormatter(new TextFormatter<>(new IntRangeStringConverter(0, 23), 0));
prepareTextField(hours);
prepareTextField(minutes);
prepareTextField(seconds);
    
HBox fields = new HBox(hours, createLabel(),minutes, createLabel(), seconds);
fields.setPadding(new Insets(4));
fields.setStyle("-fx-background-color: white;");
public static void prepareTextField(TextField tf) {
    tf.setAlignment(Pos.CENTER);
    tf.setBackground(Background.EMPTY);
    tf.setBorder(Border.EMPTY);
    tf.setPadding(Insets.EMPTY);
    tf.setPrefColumnCount(2);
}

public static class IntRangeStringConverter extends StringConverter<Integer> {

    private final int min;
    private final int max;

    public IntRangeStringConverter(int min, int max) {
        this.min = min;
        this.max = max;
    }
    
    @Override
    public String toString(Integer object) {
        return String.format("%02d", object);
    }

    @Override
    public Integer fromString(String string) {
        int integer = Integer.parseInt(string);
        if (integer > max || integer < min) {
            throw new IllegalArgumentException();
        }

        return integer;
    }

}

public static Label createLabel() {
    Label label = new Label(":");
    label.setPrefWidth(3);
    return label;
}

【讨论】:

    【解决方案2】:

    我一直在使用这个简单的类,直到对应于 DatePicker 的 TimePicker 可用为止。这里的策略是在字段失去焦点时检查条目。如果它不匹配正则表达式(可选的秒数和可选的 AM、PM、am、pm),它会通过发出哔哔声、用格式正确的条目替换条目、请求焦点并突出显示条目来吸引用户的注意力。我将 validate() 公开,以便容器(例如,对话框)也可以在关闭之前检查有效性(例如,如果按 OK 按钮失去焦点):

    public class TimeTextField extends TextField 
    {   
        public TimeTextField(String init) {
            super(init) ;
            focusedProperty().addListener((o, oldV, newV) -> changed(newV));
        }
    
        public TimeTextField() {
            this("12:00 PM");
        }
    
        private void changed(boolean focus) {
            if (!focus) {
                if (!validate()) { 
                    setText("12:00 PM");
                    selectAll();
                    requestFocus();
                    Toolkit.getDefaultToolkit().beep();
                }
            }
        }
    
        public boolean validate()  {
            return getText()
            .matches("(0?[1-9]|1[0-2]):[0-5][0-9](:[0-5][0-9])? ?[APap][mM]$");
        }    
    }
    

    【讨论】:

      【解决方案3】:

      你应该自己插入':'。因为这样用户只能插入数字。在每两个数字之后,您在更改侦听器中插入“:”。另外很容易插入时间。

      【讨论】:

      • 如果用户删除了 ':' 那么他们将无法再次添加它。
      • 是的,你是对的。 ':' 也应该是可能的。我已经为输入 IP 地址编写了一个 chaneg 侦听器,并且有一个“。”允许。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-04
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 1970-01-01
      相关资源
      最近更新 更多