Валидатор для JavaFX

Я хочу реализовать этот валидатор:

http://dev-fjord.blogspot.com/2012/11/javafx-field-validation.html

Я создал TextField, который хочу использовать для проверки номера порта:

TextField pwBox = new TextField();

        ErrorValidator<String> idValidator = new ErrorValidator<>(pwBox.textProperty(), new ITypeValidator<String>()
        {
            @Override
            public ErrorValidator.State validate(String typeToValidate)
            {
                // Whatever validation code is required
                int occurences = countOccurences(typeToValidate, '!');
                if (occurences == 0)
                {
                    return State.VALID;
                }
                else if (occurences < 3)
                {
                    return State.WARNING;
                }
                else
                {
                    return State.ERROR;
                }
            }
        }, ErrorValidator.State.VALID);

        Text idErrorLabel = null;
        idValidator.addStyleTargets(idErrorLabel, pwBox);

        idValidator.stateProperty().addListener(new ChangeListener<State>()
        {
            @Override
            public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue)
            {
                switch (newValue)
                {
                    case ERROR:
                        idErrorLabel.setText("Too many Exclamation Marks!!!");
                        break;
                    case WARNING:
                        idErrorLabel.setText("Be careful not to use too many Exclamation Marks!!!");
                        break;
                }
            }
        });

        grid.add(pwBox, 1, 2);

Валидатор:

import java.util.ArrayList;
import java.util.List;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;

/**
 * Class for giving visual feedback about the validation state of {@link ObservableValue}s.
 *
 * @param <T> The type that is validated
 */
public class ErrorValidator<T>
{
    private static final String BASE_STYLE = "validated";

    public static enum State
    {
        VALID("validation_valid"), WARNING("validation_warning"), ERROR("validation_error");

        public final String style;

        private State(String style)
        {
            this.style = style;
        }
    }

    private final List<Node> styleTargets = new ArrayList<>();
    private ObjectProperty<State> state = new SimpleObjectProperty<>(State.VALID);

    /**
     * Initializes this {@link ErrorValidator} with a state that can be different from the actual validation result.
     *
     * @param property
     * @param validator
     * @param initState
     */
    public ErrorValidator(final ObservableValue<? extends T> property, final ITypeValidator<? super T> validator, State initState)
    {
        //Preconditions.checkNotNull(initState, "The state may not be null!");
        state.set(initState);

        property.addListener(new ChangeListener<T>()
        {
            @Override
            public void changed(ObservableValue<? extends T> observable, T oldValue, T newValue)
            {
                setState(validator.validate(newValue));
            }
        });
    }

    /**
     * Initializes this {@link ErrorValidator} with a state depending on the current validation result.
     *
     * @param property
     * @param validator
     */
    public ErrorValidator(final ObservableValue<? extends T> property, final ITypeValidator<? super T> validator)
    {
        this(property, validator, validator.validate(property.getValue()));
    }

    private void setState(State newState)
    {
        if (state.get() == newState)
        {
            return;
        }
        //Preconditions.checkNotNull(newState, "The state may not be null!");

        for (Node node : styleTargets)
        {
            node.getStyleClass().remove(state.get().style);
            node.getStyleClass().add(newState.style);
        }

        this.state.set(newState);
    }

    /**
     * Adds a new {@link Node} that should receive styleclasses depending of the validation state of this validator.
     *
     * @param node
     */
    public void addStyleTarget(Node node)
    {
        styleTargets.add(node);
        node.getStyleClass().add(state.get().style);
        node.getStyleClass().add(BASE_STYLE);
    }

    /**
     * Adds new {@link Node}s that should receive styleclasses depending of the validation state of this validator.
     *
     * @param nodes
     */
    public void addStyleTargets(Node... nodes)
    {
        for (Node node : nodes)
        {
            addStyleTarget(node);
        }
    }

    public ReadOnlyObjectProperty<State> stateProperty()
    {
        return state;
    }
}

Интерфейс:

public interface ITypeValidator<T>
{
    ErrorValidator.State validate(T typeToValidate);
}

По какой-то причине, когда я запускаю приложение и открываю окно, содержащее поле ввода с валидатором, окно не открывается. У меня есть ошибка кода Java, которую я не могу найти. В Netbeans нет сообщений об ошибках. Можете ли вы помочь мне найти проблему?


person Peter Penzov    schedule 09.11.2013    source источник
comment
попробуйте удалить валидатор и открыть окно, это работает?   -  person Aakash Goyal    schedule 09.11.2013
comment
Да, когда я удаляю валидатор, он работает нормально.   -  person Peter Penzov    schedule 09.11.2013
comment
Эта проблема решена?   -  person Jens Piegsa    schedule 19.11.2013
comment
Да, я использую пример из приложения Ensemble.   -  person Peter Penzov    schedule 19.11.2013


Ответы (1)


Быстро попробовав, линия

    node.getStyleClass().add(state.get().style);

в addStyleTarget(Node node) бросает NullPointerException. Но, возможно, это потому, что я не до конца знаю ваш основной класс приложения.

person Jens Piegsa    schedule 09.11.2013