Использование Document Filter для фильтрации нескольких периодов(.)

Допустим, пользователь должен ввести значение Double в поле Jtext, которое затем будет вычислено.
Но если пользователь внезапно использовал более 1 периода, это вызовет исключение NumberFormatException, поэтому я предполагаю, что решение будет использовать фильтр документов для фильтрации. исключить любые дополнительные периоды или перехватить исключение и уведомить пользователя о недопустимом вводе

В настоящее время используется DocumentFilter, чтобы разрешать только цифры и периоды, но моя проблема заключается в том, как отфильтровать второй период

PlainDocument filter = new PlainDocument();
            filter.setDocumentFilter(new DocumentFilter() {
                    @Override
                    public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) 
                    throws BadLocationException 
                    {
                    fb.insertString(off, str.replaceAll("[^0-9.]", ""), attr);
                    } 
                    @Override
                    public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) 
                    throws BadLocationException 
                    {
                    fb.replace(off, len, str.replaceAll("[^0-9.]", ""), attr);
                    }
            });

            apm.setDocument(filter);

Пример

Неверный ВВОД: 1.2.2

Действительный ВВОД: 1,22


person JLawrence    schedule 06.10.2013    source источник
comment
понятия не имею, работает для меня, для лучшей помощи скорее опубликуйте SSCCE, короткий, исполняемый, компилируемый   -  person mKorbel    schedule 06.10.2013
comment
Я бы закодировал фильтр, чтобы просто не допускать второго периода. Что вы пробовали? Как это не работает? И привет @mKorbel!   -  person Hovercraft Full Of Eels    schedule 06.10.2013
comment
Сам буду ждать sscce.   -  person Hovercraft Full Of Eels    schedule 06.10.2013
comment
@HovercraftFullOfEels - я также использую DocumentListener для расчета значения.   -  person JLawrence    schedule 06.10.2013
comment
@HovercraftFullOfEels - как мне отфильтровать второй период?   -  person JLawrence    schedule 06.10.2013
comment
Разбирая String в try/catch и перехватывая NumberFormatException. Если нет исключений, примите проанализированный номер. Если исключение, то в блоке catch вернуть исходный номер и уведомить пользователя.   -  person Hovercraft Full Of Eels    schedule 06.10.2013
comment
Или используйте JFormattedTextField, как показано здесь   -  person Robin    schedule 06.10.2013
comment
Да, или используйте InputVerifier, как описано здесь.   -  person Hovercraft Full Of Eels    schedule 06.10.2013
comment
Отфильтровывая дополнительные '.' действительно плохо. Вы никогда не можете знать, что имел в виду пользователь. то есть: «1.2.2» -> «12.2» или «1.22». Лучше всего позволить пользователю вводить только правильные числа.   -  person Viktor Seifert    schedule 07.10.2013


Ответы (2)


Мое предложение состоит в том, что вы можете изменить переопределенные методы insertString и replace, чтобы они проверяли, были ли какие-либо "." вставлены ранее перед этой вставкой, или заменить и изменить фильтр таким образом, чтобы «период» был заменен пустой строкой, если таковая имеется в следующий раз, когда пользователь вставит символ period. Я проиллюстрировал, как показано ниже:

@Override
public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) 
                throws BadLocationException {
    String regExp;
    Document doc = fb.getDocument();
    if(doc.getText(0, doc.getLength()).indexOf(".") == -1){
        regExp = "[^0-9.]";
    } else {
        regExp = "[^0-9]";
    }
    fb.insertString(off, str.replaceAll(regExp, ""), attr);
}

@Override
public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) 
                throws BadLocationException {
    String regExp;
    Document doc = fb.getDocument();
    if(doc.getText(0, doc.getLength()).indexOf(".") == -1){
        regExp = "[^0-9.]";
    } else {
        regExp = "[^0-9]";
    }
    fb.replace(off, len, str.replaceAll(regExp, ""), attr);
}

Приведенный выше код позволит вставить «период» только один раз в Document, для которого установлен этот DocumentFilter.

person Blip    schedule 06.06.2015

Да, используйте блок try catch. Реализуйте счастливый путь (то есть правильно отформатированное число) внутри блока try и реализуйте случай ошибки в блоке catch. Например, если вы хотите выделить поле красным цветом или вывести сообщение об ошибке, вы должны поместить эту логику (или вызвать ее из) в блоке catch.

person Carlos Macasaet    schedule 06.10.2013