Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting 'Attempt to mutate notification' exception

My goal is to implement blue coloring of keywords written by user into JTextPane. This is how my code look like:

private class DocumentHandler implements DocumentListener {

        @Override
        public void changedUpdate(DocumentEvent ev) {
        }

        @Override
        public void insertUpdate(DocumentEvent ev) {
            highlight();
        }

        @Override
        public void removeUpdate(DocumentEvent ev) {
            highlight();
        }

        private void highlight() {
            String code = codePane.getText();
            SimpleAttributeSet defSet = new SimpleAttributeSet();
            StyleConstants.setForeground(defSet, Color.BLACK);
            doc.setCharacterAttributes(0, code.length(), defSet, true);
            SimpleAttributeSet set = new SimpleAttributeSet();
            StyleConstants.setForeground(set, Color.BLUE);
            for (String keyword : keywords) {
                Pattern pattern = Pattern.compile(keyword + "(\\[\\])*");
                Matcher matcher = pattern.matcher(code);
                while (matcher.find()) {

                    //Just for test
                    System.out.print("Start index: " + matcher.start());
                    System.out.print(" End index: " + matcher.end());
                    System.out.println(" Found: " + matcher.group());

                    doc.setCharacterAttributes(matcher.start(), keyword.length(), set, true);
                }
            }
        }
    }

After typing anything into pane I get:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
    at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1338)
    at javax.swing.text.DefaultStyledDocument.setCharacterAttributes(DefaultStyledDocument.java:500)
    at jnotepad.MainPanel$DocumentHandler.highlight(MainPanel.java:121)
    at jnotepad.MainPanel$DocumentHandler.insertUpdate(MainPanel.java:108)
    at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:202)
    at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)

How to solve my problem? Maybe I should use something other than DocumentListener?

like image 794
user2102972 Avatar asked Mar 04 '13 16:03

user2102972


2 Answers

You need to invoke changes to the document from the Event Dispatcher Thread.

Try this:

private void highlight() {

    Runnable doHighlight = new Runnable() {
        @Override
        public void run() {
            // your highlight code
        }
    };       
    SwingUtilities.invokeLater(doHighlight);
}
like image 170
moeTi Avatar answered Nov 18 '22 19:11

moeTi


I had the same problem, I solved it by using this:

expiration_timeTF.getDocument().addDocumentListener(
            new DocumentListener() {
                @Override
                public void removeUpdate(DocumentEvent e) {
                    System.out.println("remove");
                }

                private void assistDateText() {
                    Runnable doAssist = new Runnable() {
                        @Override
                        public void run() {
                            // when input "2013",will add to "2013-";when
                            // input "2013-10",will add to "2013-10-"
                            String input = expiration_timeTF.getText();
                            if (input.matches("^[0-9]{4}")) {
                                expiration_timeTF.setText(input + "-");
                            } else if (input.matches("^[0-9]{4}-[0-9]{2}")) {
                                expiration_timeTF.setText(input + "-");
                            }
                        }
                    };
                    SwingUtilities.invokeLater(doAssist);
                }

                @Override
                public void insertUpdate(DocumentEvent e) {
                    // System.out.println("insert");
                    assistDateText();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    // System.out.println("change");
                }
            });
like image 45
user2845064 Avatar answered Nov 18 '22 19:11

user2845064