验证多个输入字段时如何避免重复代码?

How to avoid duplicate code when validating multiple input fields?

如何在验证 TextFields、DatePickers、ChoiceBoxes 等多个输入字段时避免重复代码?下面的代码属于 class 服务,StageAddController 使用它来侦听和验证输入。当焦点丢失且字段为空时,字段边框变为红色。

public void validateForEmptyTextField(TextField textField, PseudoClass errorClass){
    textField.focusedProperty().addListener((arg0, oldValue, newValue) -> {
        if (!newValue) { //when focus lost
            if(textField.getText().trim().isEmpty()){
                textField.pseudoClassStateChanged(errorClass, true);
            }
            else
                textField.pseudoClassStateChanged(errorClass, false);
        }
    });
}

public void validateForEmptyDatePicker (DatePicker datePicker, PseudoClass errorClass){
    datePicker.focusedProperty().addListener((arg0, oldValue, newValue) -> {
        if (!newValue) { //when focus lost
            if(datePicker.getValue() == null){
                datePicker.pseudoClassStateChanged(errorClass, true);
            }
            else
                datePicker.pseudoClassStateChanged(errorClass, false);
        }
    });
}

public void validateForEmptyChoiceBox (ChoiceBox<String > stringChoiceBox, PseudoClass errorClass){
    stringChoiceBox.focusedProperty().addListener((arg0, oldValue, newValue) -> {
        if (!newValue) { //when focus lost
            if(stringChoiceBox.getValue() == null){
                stringChoiceBox.pseudoClassStateChanged(errorClass, true);
            }
            else
                stringChoiceBox.pseudoClassStateChanged(errorClass, false);
        }
    });
}

可以通过引入扩展Node (1) 的通用参数T 并传递一个Predicate<T> (2):

来实现
public <T extends Node> void validateNodeForEmptyByPredicate(
    T node,
    PseudoClass errorClass,
    Predicate<T> predicate
) {
    node.focusedProperty().addListener((arg0, oldValue, newValue) -> {
        if (!newValue) {
            node.pseudoClassStateChanged(errorClass, predicate.test(node)); // *
        }
    });
}
  • (1)需要访问focusedProperty方法;
  • (2) 判断 T 是否为空,例如:
    • 持续 TextField 秒 -> field -> field.getText().trim().isEmpty()
    • 持续 DatePicker 秒 -> picker -> picker -> picker.getValue() == null
    • for ChoiceBoxes -> box -> box.getValue() == null.

我想重写以下代码块(*)

if (predicate.test(node)) {
    node.pseudoClassStateChanged(errorClass, true);
} else {  
    node.pseudoClassStateChanged(errorClass, false);
}

进入:

node.pseudoClassStateChanged(errorClass, predicate.test(node));