Javafx 2 JavaFX2.2 FXML验证文本字段

Javafx 2 JavaFX2.2 FXML验证文本字段,javafx-2,validation,textfield,fxml,Javafx 2,Validation,Textfield,Fxml,我改进了以前的TextField验证实现,这次使用绑定实现了一个具有实时验证的真正自定义控件。它可以与FXML一起使用,而不需要更多的Java代码 import javafx.beans.binding.BooleanBinding; import javafx.beans.property.BooleanProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ReadOnlyBoo

我改进了以前的TextField验证实现,这次使用绑定实现了一个具有实时验证的真正自定义控件。它可以与FXML一起使用,而不需要更多的Java代码

import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.paint.Color;

/**
 * <p>
 * TextField with regex-based real-time input validation.
 * JavaFX 2 and FXML compatible. </p>
 * <p>
 * FXML code example:<div>
 *  {@code <ValidatedTextField fx:id="validatedTextField" minLength="1" maxLength="1" mask="^[0-9]*$" />}
 * </div>
 * </p>
 * 
 * @author 82300009
 */
public final class ValidatedTextField extends TextField {

    private final BooleanProperty invalid = new SimpleBooleanProperty(false);
    private final StringProperty mask;
    private final IntegerProperty minLength;
    private final IntegerProperty maxLength;

    private Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);

    public ValidatedTextField() {
        super();
        this.mask = new SimpleStringProperty(".");
        this.minLength = new SimpleIntegerProperty(-1);
        this.maxLength = new SimpleIntegerProperty(-1);

        bind();
    }

    public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable) {
        this(mask, minLength, maxLength, nullable, null);
    }

    public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable, String string) {
        super(string);
        this.mask = new SimpleStringProperty(mask);
        this.minLength = new SimpleIntegerProperty(minLength);
        this.maxLength = new SimpleIntegerProperty(maxLength);

        bind();
    }

    public ReadOnlyBooleanProperty invalidProperty() {
        return invalid;
    }

    public ReadOnlyStringProperty maskProperty() {
        return mask;
    }

    public ReadOnlyIntegerProperty minLengthProperty() {
        return minLength;
    }

    public ReadOnlyIntegerProperty maxLengthProperty() {
        return maxLength;
    }

    public boolean getInvalid() {
        return invalid.get();
    }

    public String getMask() {
        return mask.get();
    }

    public void setMask(String mask) {
        this.mask.set(mask);
    }

    public int getMinLength() {
        return minLength.get();
    }

    public void setMinLength(int minLength) {
        this.minLength.set(minLength);
    }

    public int getMaxLength() {
        return maxLength.get();
    }

    public void setMaxLength(int maxLength) {
        this.maxLength.set(maxLength);
    }

    public Effect getInvalidEffect() {
        return this.invalidEffect;
    }

    public void setInvalidEffect(Effect effect) {
        this.invalidEffect = effect;
    }

    private void bind() {
        this.invalid.bind(maskCheck().or(minLengthCheck()));

        this.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> ov, String t, String t1) {
                if (textProperty().get().length() > maxLength.get()) {
                    setText(t);
                }
            }
        });

        this.invalid.addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (t ^ t1) {
                    if (t1) {
//                        setStyle("-fx-font-weight: bold; -fx-text-fill: red;");
                        setEffect(invalidEffect);
                    } else {
//                        setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;");
                        setEffect(null);
                    }
                }

            }
        });
    }

    private BooleanBinding maskCheck() {
        return new BooleanBinding() {
            {
                super.bind(textProperty(), mask);
            }

            @Override
            protected boolean computeValue() {
                return !textProperty().get().matches(mask.get());
            }
        };
    }

    private BooleanBinding minLengthCheck() {
        return new BooleanBinding() {
            {
                super.bind(textProperty(), minLength);
            }

            @Override
            protected boolean computeValue() {
                return textProperty().get().length() < minLength.get();
            }
        };
    }

    private BooleanBinding maxLengthCheck() {
        return new BooleanBinding() {
            {
                super.bind(textProperty(), maxLength);
            }

            @Override
            protected boolean computeValue() {
                return textProperty().get().length() > maxLength.get();
            }
        };
    }
}
导入javafx.beans.binding.BooleanBinding;
导入javafx.beans.property.BooleanProperty;
导入javafx.beans.property.IntegerProperty;
导入javafx.beans.property.ReadOnlyBooleanProperty;
导入javafx.beans.property.ReadOnlyIntegerProperty;
导入javafx.beans.property.ReadOnlyStringProperty;
导入javafx.beans.property.SimpleBoleAnProperty;
导入javafx.beans.property.SimpleIntegerProperty;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.scene.control.TextField;
导入javafx.scene.effect.BlurType;
导入javafx.scene.effect.DropShadow;
导入javafx.scene.effect.effect;
导入javafx.scene.paint.Color;
/**
*
*基于正则表达式的实时输入验证的TextField。
*JavaFX2和FXML兼容

* *FXML代码示例: *{@code} * *

* *@author 82300009 */ 公共最终类ValidatedTextField扩展了TextField{ private final BooleanProperty invalid=新的SimpleBoleanProperty(false); 私人财产面具; 私有最终IntegerProperty minLength; 私有最终IntegerProperty maxLength; private Effect invalidEffect=新的DropShadow(BlurType.GAUSSIAN,Color.RED,4,0.0,0,0); 公共ValidatedTextField(){ 超级(); this.mask=新的SimpleStringProperty(“.”); this.minLength=新的SimpleIntegerProperty(-1); this.maxLength=新的SimpleIntegerProperty(-1); bind(); } 公共ValidatedTextField(字符串掩码、int-minLength、int-maxLength、布尔值可为空){ 这(掩码、minLength、maxLength、nullable、null); } 公共ValidatedTextField(字符串掩码、int-minLength、int-maxLength、布尔值可空、字符串){ 超级(字符串); this.mask=新的SimpleStringProperty(mask); this.minLength=新的SimpleIntegerProperty(minLength); this.maxLength=新的SimpleIntegerProperty(maxLength); bind(); } public ReadOnlyBooleanProperty invalidProperty(){ 返回无效; } 公共ReadOnlyStringProperty maskProperty(){ 返回掩码; } 公共只读集成属性minLengthProperty(){ 返回最小长度; } 公共只读集成属性maxLengthProperty(){ 返回最大长度; } 公共布尔getInvalid(){ 返回无效的.get(); } 公共字符串getMask(){ 返回mask.get(); } 公共void设置掩码(字符串掩码){ 此.mask.set(mask); } 公共int getMinLength(){ 返回minLength.get(); } 公共void setMinLength(int minLength){ this.minLength.set(minLength); } public int getMaxLength(){ 返回maxLength.get(); } 公共void setMaxLength(int maxLength){ this.maxLength.set(maxLength); } 公共效果GetInvalideEffect(){ 返回此.invalidEffect; } 公共无效设置无效效果(效果){ this.invalidEffect=效果; } 私有无效绑定(){ 此.invalid.bind(maskCheck()或(minLengthCheck()); this.textProperty().addListener(新的ChangeListener()){ @凌驾
public void changed(observevalue您始终可以通过将样式从样式类列表中删除来恢复样式,即

node.getStyleClass().remove("my-style");

我现在正在使用它,但它看起来相当慢…而且它没有应用伪状态:invalid。它不应该读取无效的变量值并应用伪状态吗?我使用了添加/删除样式技术,但没有发现它慢,您可能需要测量这部分代码是否真的是问题所在。您需要实现一个外观以具有其他状态请参阅一些代码示例。我猜是这样的。事实上,我现在正在观看关于创建自定义控件()以实现适当的可再发行控件的JavaOne 2011教程。我也将看看github,非常感谢!
node.getStyleClass().remove("my-style");