0

I've been struggling to wrap my head around this DocumentFilter business, and just when I feel like I understood it mostly, I tried out a simple test case that just didn't make any sense.

So the goal initially was to create a simple DocumentFilter to allow numbers only, including decimals. I did some research and read up on the few posts already existing here on StackOverflow that detail the process very well. Thank you to those who posted in those. I also read up on Regex for the first time and had my mind blown by how versatile it is.

Moving on, I wrote (mostly copied) one of the examples and tried it out on my program, but for some reason it just wasn't working. I decided to go back to basics and try out a very very simple subclass of 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);
    }
}

This is what is really throwing me off now. From the oracle documents, I read that insertString is to insert stuff (I'm assuming where the cursor is) and replace is to replace (such as for Copy and Paste). Now clearly I'm misunderstanding something here because the JTextField that I use setDocumentFilter on only lets me "insert" A's and not B's. Can someone please explain how these methods actually work?

If I can get this figured out I will later post what I had for the actual IntegerFilter to see if I can get that worked out as well.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Edward Guo
  • 175
  • 1
  • 13

2 Answers2

2

When you type text into a JTextComponent, the replace(...) method of the DocumentFilter will be invoked. This is because the replaceSelection(...) method of the JTextComponent ends up being invoked by the text insert action.

If you insert text directly into the Document using the insertString(...) method of the Document, then the insertString(...) method of the DocumentFilter will be invoked.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • So then for a JTextField where I'm just trying to filter numbers, is there any reason to even overwrite the insertString method? – Edward Guo Dec 18 '15 at 02:07
  • @EdwardGuo Not really, but I always just create a method that can be invoked from both the replace() and insertString() methods, just in case you ever add code to manually update the Document. – camickr Dec 18 '15 at 02:09
  • @EdwardGuo, the `replaceSelection(...)` method used by the text components needs to handle the case when text is selected and when text isn't selected when you type/paste text into the text component. So a single method is used which maps to a single method in the `DocumentFilter`. – camickr Dec 18 '15 at 02:23
  • So, your question has been answered. Your question was not about how to write an Integer filter. Why are you even bothering with such a complicated regex which is not required? Just using `Integer.parseInt(...)`. – camickr Dec 18 '15 at 02:26
  • Wait, what? How would I use that to check to see if the input is a number? Sorry, it should also be DoubleFilter I guess to be more specific. – Edward Guo Dec 18 '15 at 02:32
  • @EdwardGuo, Not sure I understand the question? That method converts a String to an int. So if the conversion is successful you invoke super.replace() otherwise to nothing. Also, what's wrong with `Double.parseDouble(...)` ? – camickr Dec 18 '15 at 02:49
  • I'm just not sure how I would use that to make sure it is a double. Is there a way to implement it so that it's a boolean check? – Edward Guo Dec 18 '15 at 02:53
  • @EdwardGuo, There is no need for a Boolean check. You need to use a try/catch block when using the parseDouble(..) method. So the code in the try block is just to invoke the parseDouble(...) method and then invoke super.replace(...). So you assume the parsing will work. If it doesn't then the catch block will be executed and the super.replace(...) will be ignored. – camickr Dec 18 '15 at 15:47
  • Oh okay, I haven't worked with try/catch that much, so it didn't occur to me. Thanks for the tip. – Edward Guo Dec 18 '15 at 17:40
1

The documentation for the DocumentFilter class can be found here You have three methods in the class:

InsertString():

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

Invoked prior to insertion of text into the specified Document.

Remove():

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

Invoked prior to removal of the specified region in the specified Document.

Replace():

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

Invoked prior to replacing a region of text in the specified Document.

The InsertString() method appears to be used for editing documents.From my past experience, to change the text in a JTextField, you need to use a DocumentListener like this example.

Community
  • 1
  • 1
Ryan
  • 1,972
  • 2
  • 23
  • 36