Есть ли способ принудительно проверить после применения формата к JFormattedTextField?

Первое, что я делаю, это создаю NumberFormat, который соответствует моим потребностям:

this.format = NumberFormat.getIntegerInstance();
this.format.setMinimumIntegerDigits(6);
this.format.setMaximumIntegerDigits(6);
this.format.setGroupingUsed(false);

Затем я применяю его к JFormattedTextField:

this.fld_id = new JFormattedTextField(this.format);

Затем я устанавливаю InputVerifier этого поля, например:

this.fld_id.setInputVerifier(new IdVerifier());

Мой IdVerifier просто проверяет, соответствует ли введенный текст регулярному выражению:

private class IdVerifier extends InputVerifier {
        public boolean verify(final JComponent arg0) {
            final JFormattedTextField verifyJTF = (JFormattedTextField) arg0;

            if (!verifyJTF.getText().matches("\\d{6}")) {
                return false;
            }

            return true;
        }

        public boolean shouldYieldFocus(final JComponent arg0) {
            if (!this.verify(arg0)) {
                arg0.setBackground(Color.RED);
            } else {
                arg0.setBackground(UIManager.getColor("TextField.background"));
            }

            return true;
        }
}

Однако, когда я это делаю, я ввожу значение в JFormattedTextField, скажем, «1». Это переформатируется в «000001» с помощью NumberFormatter. Однако в этом примере фон текстового поля по-прежнему имеет красный цвет.

Каков правильный способ гарантировать, что отформатированное содержимое JFormattedTextField будет потребляться InputVerifier? Я ожидал, что поведение по умолчанию будет заключаться в том, что фокус будет потерян, форматтер будет применен, а затем будет проверен ввод. Однако это явно не так.


person Thomas Owens    schedule 24.04.2013    source источник


Ответы (2)


Глядя на определение InputVerifier, не похоже, что работа с графическим интерфейсом должна происходить внутри методов verify или shouldYieldFocus. InputVerifier предназначен исключительно для принятия решения о том, должен ли фокус перемещаться с одного поля на другое.

Я думаю, вам лучше прикрепить ActionListener к вашему JFormattedTextField, а затем просто вызвать код регулярного выражения и красной окраски в теле этого слушателя. Затем проверка будет производиться каждый раз при изменении содержимого текстового поля.

person Bobulous    schedule 24.04.2013
comment
В учебниках в разделе Проверка ввода они издают звуковой сигнал в InputVerifier. Что в определении InputVerifier заставляет вас думать, что вы не должны делать что-то с графическим интерфейсом в нем, особенно с JComponent, к которому у InputVerifier есть доступ? - person Thomas Owens; 24.04.2013
comment
Хорошая мысль, и хотя в описании shouldYieldFocus просто говорится о вызовах verify() для проверки правильности ввода, в нем упоминается, что метод может иметь побочные эффекты. Но я все еще думаю, что ActionListener лучше подходит, и я думаю, что это решит вашу проблему, когда речь идет о NumberFormatter. - person Bobulous; 24.04.2013
comment
Вместо этого я рассмотрю возможность использования ActionListener, но это кажется странным поведением. Я подтвердил, что в verify() текст входного аргумента действительно является значением до форматирования. Думаю, я просто ожидал, что средство форматирования будет вызываться перед верификатором, чтобы вы проверяли форматированный ввод (например, регулярное выражение, как я делаю). - person Thomas Owens; 24.04.2013
comment
Но InputVerifier вызывается только тогда, когда поле теряет фокус, поэтому он не вызывается, когда NumberFormatter меняет свое значение. В обоих случаях следует вызывать ActionListener. - person Bobulous; 24.04.2013
comment
Это правда. Думаю, я сделал предположение, что NumberFormatter будет вызываться перед InputVerifier, когда поле теряет фокус. - person Thomas Owens; 25.04.2013

Измените регулярное выражение на \\d{1,6}, оно, вероятно, не принимает начальные нули в качестве числа.

person Mr Rho    schedule 24.04.2013
comment
Я давно не занимался графическим интерфейсом, но Oracle в учебниках предлагается делать это по-моему, поэтому я так и сделал. В разделе «Проверка ввода» они вызывают метод звукового сигнала в методе shouldYieldFocus(). Я не вижу разницы между изменением цвета поля и звуковым сигналом. Это может быть плохим примером в учебниках, но я не понимаю, как перенос настроек фона из метода verify() в метод shouldYieldFocus() что-то решит. - person Thomas Owens; 24.04.2013
comment
Да, тоже прочитайте это сейчас, моя ошибка - возможно, это связано с обычным выражением... прочитайте мою обновленную запись. - person Mr Rho; 24.04.2013
comment
Однако это меняет смысл моего регулярного выражения. Вероятно, это сработает благодаря форматтеру, но я не хочу полагаться на наличие форматтера. {1,6} означает не менее 1, но не более 6 раз — единственный допустимый ввод — ровно 6 цифр. - person Thomas Owens; 24.04.2013
comment
@MrRho Проблема не в правильности регулярного выражения, а в способе выполнения кода. - person Bobulous; 24.04.2013
comment
Согласен, извиняюсь за ввод в заблуждение. - person Mr Rho; 24.04.2013