java 获取“尝试改变通知”异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15206586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:50:55  来源:igfitidea点击:

Getting 'Attempt to mutate notification' exception

javaswingjtextpane

提问by user2102972

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

我的目标是在 JTextPane 中实现用户编写的关键字的蓝色着色。这是我的代码的样子:

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?

如何解决我的问题?也许我应该使用 DocumentListener 以外的东西?

回答by moeTi

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

您需要从 Event Dispatcher Thread 调用对文档的更改。

Try this:

试试这个:

private void highlight() {

    Runnable doHighlight = new Runnable() {
        @Override
        public void run() {
            // your highlight code
        }
    };       
    SwingUtilities.invokeLater(doHighlight);
}

回答by user2845064

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");
                }
            });