在写一个记事本,想实现Ultraedit即时Java关键字染色的功能。
我使用的文本框是JTextPane,利用DocumentListener监听文本改变,并及时对改变的区域进行染色。
可问题是当我判断一个单词是关键字时,我得先删去这个词,然后将字体换为红色在插入原来位置。
这样会造成DocumentListener发生死循环,想请教大家是如何处理的。
(是要及时响应文本变化,而不是输完文本后按一个按钮才开始染色)
java.lang.IllegalStateException: Attempt to mutate in notification
        at javax.swing.text.AbstractDocument.writeLock(Unknown Source)
        at javax.swing.text.AbstractDocument.remove(Unknown Source)
        at MyEditor.dealChange(MyEditor.java:215)
        at MyEditor.dealChange(MyEditor.java:200)
        at MyEditor.dealChange(MyEditor.java:154)
        at MyEditor.access$400(MyEditor.java:36)
        at MyEditor$MyDocumentListener.valueChanged(MyEditor.java:291)
        at MyEditor$MyDocumentListener.insertUpdate(MyEditor.java:275)
        at javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
        at javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
        at javax.swing.text.AbstractDocument.insertString(Unknown Source)
        at javax.swing.text.AbstractDocument.replace(Unknown Source)
        at javax.swing.JTextPane.replaceSelection(Unknown Source)
        at javax.swing.JTextPane.replaceSelection(Unknown Source)
        at javax.swing.text.DefaultEditorKit$DefaultKeyTypedAction.actionPerform
ed(Unknown Source)
        at javax.swing.SwingUtilities.notifyAction(Unknown Source)
        at javax.swing.JComponent.processKeyBinding(Unknown Source)
        at javax.swing.JComponent.processKeyBindings(Unknown Source)
        at javax.swing.JComponent.processKeyEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
        at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)        at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Sour
ce)
        at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Sour
ce)
        at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

解决方案 »

  1.   

    什么意思?
    catch(IllegalStateException e)?这样的话虽然程序能继续运行,可是文字不会被染色啊doc.remove(start, len);//////在这一步还未完成时就会抛出异常,即使捕获,文本还是没改变啊
    doc.insertString(start, word, attrSet);
      

  2.   

    没做过这个东西,大概看了下文档,楼主写的两句代码我猜测是在DocumentListener中写的,其实也就是说当文档发生变化了,会调用DocumentListener,但是在DocumentListener中,你做了remove和insertString操作,这样又引起文档变化,于是文档又通知DocumentListener,这样就死循环了看了一下,貌似怎么改都会触动到DocumentListener,于是,有个笨办法,你先试试,捕获JTextPane的addPropertyChangeListener,当属性发生改变的时候,把JTextPane中输入的String取出来,用这些String构造一个Document,然后在set到JTextPane中,我觉得这样应该是可行的
      

  3.   

    可为什么removeDocumentListener不行呢?
    doc.removeDocumentListener(***);
    do....
    doc.addDocumentListener(***);