java change the document in DocumentListener

自古美人都是妖i 提交于 2019-11-26 16:44:16

DocumentListener is really only good for notification of changes and should never be used to modify a text field/document.

Instead, use a DocumentFilter

Check here for examples

FYI

The root course of your problem is that the DocumentListener is notified WHILE the document is been updated. Attempts to modify the document (apart from risking a infinite loop) put the document into a invalid state, hence the exception

Updated with an example

This is VERY basic example...It doesn't handle insert or remove, but my testing had remove working without doing anything anyway...

public class TestHighlight {

    public static void main(String[] args) {
        new TestHighlight();
    }

    public TestHighlight() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JTextPane textPane = new JTextPane(new DefaultStyledDocument());
                ((AbstractDocument) textPane.getDocument()).setDocumentFilter(new HighlightDocumentFilter(textPane));
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(textPane));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class HighlightDocumentFilter extends DocumentFilter {

        private DefaultHighlightPainter highlightPainter = new DefaultHighlightPainter(Color.YELLOW);
        private JTextPane textPane;
        private SimpleAttributeSet background;

        public HighlightDocumentFilter(JTextPane textPane) {
            this.textPane = textPane;
            background = new SimpleAttributeSet();
            StyleConstants.setBackground(background, Color.RED);
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
            System.out.println("insert");
            super.insertString(fb, offset, text, attr);
        }

        @Override
        public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
            System.out.println("remove");
            super.remove(fb, offset, length);
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {

            String match = "test";

            super.replace(fb, offset, length, text, attrs);

            int startIndex = offset - match.length();
            if (startIndex >= 0) {

                String last = fb.getDocument().getText(startIndex, match.length()).trim();
                System.out.println(last);
                if (last.equalsIgnoreCase(match)) {

                    textPane.getHighlighter().addHighlight(startIndex, startIndex + match.length(), highlightPainter);

                }

            }
        }

    }

}

while the user types i want to delete the contents of JTextPane and insert a customized text instead.

Wrap the code you call in SwingUtilities.invokeLater()

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!