如何格式化文本字段javafx

时间:2016-02-10 06:21:42

标签: regex javafx textfield text-formatting

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

namespace App\Http\Controllers;

use App\Repositories\SearchRepository

class SearchController extends Controller {

    public function __construct(SearchRepository $search) {
        $this->search       = $search;
    }

    public function searchAction() {
        $result = $this->search->getDetails();

        // return to view or whatever
    }

    public function printAction() {
        $result = $this->search->getDetails();

        // print excel code or whatever
    }
}

我还有一个限制文本字段允许的字符数量的方法:

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

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

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

使用SimpleDateFormat

已经设计了一个用于格式化日期的类,您可以将其用于TextField's textFormatterSimpleDateFormat

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种不同的TextFields

您还可以使用3个不同的TextField并删除背景和边框,并将它们放在HBox中以获取不可编辑的:

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

答案 1 :(得分: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]$");
    }    
}

答案 2 :(得分:-1)

您应该插入&#39;:&#39;靠自己。因为这样用户只允许插入数字。在每两个数字后面插入&#39;:&#39;在改变监听器内部。另外很容易插入时间。