Что именно делает каждый из методов (и аргументов) DocumentFilter?

Я изо всех сил пытался уложить в голове все, что связано с DocumentFilter, и именно тогда, когда я почувствовал, что понял его в основном, я попробовал простой тестовый пример, который просто не имел никакого смысла.

Таким образом, изначально целью было создать простой DocumentFilter, разрешающий только числа, включая десятичные дроби. Я провел некоторое исследование и прочитал несколько сообщений, уже существующих здесь, на StackOverflow, которые очень хорошо детализируют процесс. Спасибо тем, кто написал в тех. Я также впервые прочитал о Regex и был потрясен его универсальностью.

Двигаясь дальше, я написал (в основном скопировал) один из примеров и попробовал его в своей программе, но по какой-то причине он просто не работал. Я решил вернуться к основам и попробовать очень простой подкласс DocumentFilter:

public class SomeFilter extends DocumentFilter {

    public void insertString(FilterBypass fb, int offs, String str,
        AttributeSet a) throws BadLocationException {

        if (str.matches("B")) super.insertString(fb, offs, str, a);
    }

    public void replace(FilterBypass fb, int offs, int len, String str,
        AttributeSet a) throws BadLocationException {

        if (str.matches("A")) super.replace(fb, offs, len, str, a);
    }
}

Это то, что действительно сбивает меня с толку сейчас. Из документов оракула я прочитал, что вставкаString предназначена для вставки материала (я предполагаю, где находится курсор), а замена - для замены (например, для копирования и вставки). Теперь ясно, что я что-то неправильно понимаю, потому что JTextField, для которого я использую setDocumentFilter, позволяет мне «вставлять» только A, а не B. Может кто-нибудь объяснить, как на самом деле работают эти методы?

Если я смогу понять это, я позже опубликую то, что у меня было для фактического IntegerFilter, чтобы посмотреть, смогу ли я это сделать.


person Edward Guo    schedule 18.12.2015    source источник


Ответы (2)


Когда вы вводите текст в JTextComponent, будет вызываться метод replace(...) DocumentFilter. Это связано с тем, что метод replaceSelection(...) объекта JTextComponent вызывается действием вставки текста.

Если вы вставите текст непосредственно в Document, используя метод insertString(...) Document, то будет вызван метод insertString(...) DocumentFilter.

person camickr    schedule 18.12.2015
comment
Итак, для JTextField, где я просто пытаюсь отфильтровать числа, есть ли какая-то причина даже перезаписывать метод insertString? - person Edward Guo; 18.12.2015
comment
@EdwardGuo Не совсем так, но я всегда просто создаю метод, который можно вызывать как из методов replace(), так и из методов insertString(), на тот случай, если вы когда-нибудь добавите код для ручного обновления документа. - person camickr; 18.12.2015
comment
@EdwardGuo, метод replaceSelection(...), используемый текстовыми компонентами, должен обрабатывать случай, когда текст выделен и когда текст не выделен при вводе/вставке текста в текстовый компонент. Таким образом, используется один метод, который сопоставляется с одним методом в DocumentFilter. - person camickr; 18.12.2015
comment
Итак, на ваш вопрос ответили. Ваш вопрос был не о том, как написать целочисленный фильтр. Почему вы вообще возитесь с таким сложным регулярным выражением, которое не требуется? Просто используя Integer.parseInt(...). - person camickr; 18.12.2015
comment
Чего ждать? Как бы я использовал это, чтобы проверить, является ли ввод числом? Извините, это также должен быть DoubleFilter, я думаю, чтобы быть более конкретным. - person Edward Guo; 18.12.2015
comment
@EdwardGuo, не уверен, что понял вопрос? Этот метод преобразует String в int. Поэтому, если преобразование прошло успешно, вы вызываете super.replace(), в противном случае ничего не происходит. Кроме того, что не так с Double.parseDouble(...) ? - person camickr; 18.12.2015
comment
Я просто не уверен, как бы я использовал это, чтобы убедиться, что это двойной. Есть ли способ реализовать это так, чтобы это была логическая проверка? - person Edward Guo; 18.12.2015
comment
@EdwardGuo, логическая проверка не нужна. Вам нужно использовать блок try/catch при использовании метода parseDouble(..). Таким образом, код в блоке try предназначен только для вызова метода parseDouble(...), а затем для вызова super.replace(...). Таким образом, вы предполагаете, что синтаксический анализ будет работать. Если это не так, блок catch будет выполнен, а super.replace(...) будет проигнорирован. - person camickr; 18.12.2015
comment
О, ладно, я не так много работал с try/catch, поэтому мне это не пришло в голову. Спасибо за совет. - person Edward Guo; 18.12.2015

Документацию по классу DocumentFilter можно найти здесь В классе есть три метода:

ВставитьСтроку():

insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr)

Вызывается перед вставкой текста в указанный документ.

Удалять():

remove(DocumentFilter.FilterBypass fb, int offset, int length)

Вызывается перед удалением указанной области в указанном документе.

Заменять():

replace(DocumentFilter.FilterBypass fb, int offset,
     int length, String text, AttributeSet attrs)

Вызывается перед заменой области текста в указанном документе.

Метод InsertString(), по-видимому, используется для редактирования документов. Из моего прошлого опыта, чтобы изменить текст в JTextField, вам нужно использовать DocumentListener, например этот пример.

person Ryan    schedule 18.12.2015