Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the DocumentFilter not give the intended result?

I figure this must be a simple mistake in the code or a misunderstanding on my part, but I cannot get a DocumentFilter to detect insertString events. Below is a simple filter for upper case letters, but that is not as important as the fact that the insertString(..) method never seems to be called!

Why is the insertString(..) method of the DocumentFilter not called?

The filter is applied to the JTextField at the top. Every time insertString(..) is called, it should append information to the JTextArea in the CENTER. At the moment, there is no action in the text field that causes text to be appended to the text area.

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.*;

public class FilterUpperCaseLetters {

    private JComponent ui = null;
    private final JTextField textField = new JTextField(25);
    private final JTextArea textArea = new JTextArea(5, 20);

    FilterUpperCaseLetters() {
        initUI();
    }

    public void initUI() {
        // The document filter that seems to do nothing.
        DocumentFilter capsFilter = new DocumentFilter() {
            @Override
            public void insertString(
                    DocumentFilter.FilterBypass fb,
                    int offset,
                    String string,
                    AttributeSet attr) throws BadLocationException {
                textArea.append("insertString! " + string + "\n");
                if (!string.toUpperCase().equals(string)) {
                    textArea.append("Insert!\n");
                    super.insertString(fb, offset, string, attr);
                } else {
                    textArea.append("DON'T insert!\n");
                }
            }
        };
        AbstractDocument abstractDocument
                = (AbstractDocument) textField.getDocument();
        abstractDocument.setDocumentFilter(capsFilter);

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        ui.add(textField, BorderLayout.PAGE_START);
        ui.add(new JScrollPane(textArea), BorderLayout.CENTER);
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                FilterUpperCaseLetters o = new FilterUpperCaseLetters();

                JFrame f = new JFrame(o.getClass().getSimpleName());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
like image 550
Andrew Thompson Avatar asked Jul 18 '15 03:07

Andrew Thompson


People also ask

What is the use of documentfilter?

DocumentFilter, as the name implies, is a filter for the Document mutation methods. When a Document containing a DocumentFilter is modified (either through insert or remove), it forwards the appropriate method invocation to the DocumentFilter. The default implementation allows the modification to occur.

What happens when a document containing a documentfilter is modified?

When a Document containing a DocumentFilter is modified (either through insert or remove ), it forwards the appropriate method invocation to the DocumentFilter. The default implementation allows the modification to occur.

What is documentfilterextends in Java?

javax.swing.text Class DocumentFilter java.lang.Object javax.swing.text.DocumentFilter public class DocumentFilterextends Object DocumentFilter, as the name implies, is a filter for the Documentmutation methods.

Which mutation methods should not be used with documentfilter?

By default, text related document mutation methods such as insertString, replaceand removein AbstractDocumentuse DocumentFilterwhen available, and Elementrelated mutation methods such as create, insertand removeElementin DefaultStyledDocumentdo not use DocumentFilter.


1 Answers

The text components use the replaceSelection(...) method which will in turn invoke the replace(...) method of the AbstractDocument which will invoke the replace(...) method of the DocumentFilter.

The insertString(...) method of the DocumentFilter is only called when you use the Document.insertString(...) method to directly update the Document.

So in reality you need to override both methods to make sure the upper case conversion is done.

A simple example showing how to easily implement both methods:

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

public class UpperCaseFilter extends DocumentFilter
{
    public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
        throws BadLocationException
    {
        replace(fb, offs, 0, str, a);
    }

    public void replace(FilterBypass fb, final int offs, final int length, final String text, final AttributeSet a)
        throws BadLocationException
    {
        if (text != null)
        {
            super.replace(fb, offs, length, text.toUpperCase(), a);
        }
    }

    private static void createAndShowGUI()
    {
        JTextField textField = new JTextField(10);
        AbstractDocument doc = (AbstractDocument) textField.getDocument();
        doc.setDocumentFilter( new UpperCaseFilter() );

        JFrame frame = new JFrame("Upper Case Filter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout( new java.awt.GridBagLayout() );
        frame.add( textField );
        frame.setSize(220, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}
like image 187
camickr Avatar answered Nov 15 '22 03:11

camickr