I use a DocumentListener
to handle any change in a JTextPane
document. while the user types i want to delete the contents of JTextPane
and insert a customized text instead. it is not possible to change the document in the DocumentListener
,instead a solution is said here:
java.lang.IllegalStateException while using Document Listener in TextArea, Java
,but i don't understand that, at least i don't know what to do in my case?
-
1DocumentLister is to `listen` to the changes to Document, not to change it – TheWhiteRabbit Feb 06 '13 at 11:12
3 Answers
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);
}
}
}
}
}

- 343,457
- 22
- 230
- 366
-
-
From what I understand, the DocumentFilter will allow you update the Document as it is been changed – MadProgrammer Feb 06 '13 at 11:17
-
This will allow you to remove text and insert new text and filter out unwanted text – MadProgrammer Feb 06 '13 at 11:19
-
each time that user types a key, i want to get the complete text in the `JTextPane`, then empty the field, insert customized text(just the text which had been entered but some keywords are colored), i think DocumentFilter is not a good suggestion for this case, what do you think? – Soheil Feb 06 '13 at 11:36
-
The short answer is, yes. The long answer is, what exactly are you trying to accomplish? Are you modifying the text pane the user is typing into or another field? – MadProgrammer Feb 06 '13 at 11:44
-
I want to modify the textPane the user is typing into, and i told you what the modify is (coloring keywords) – Soheil Feb 06 '13 at 11:46
-
Ah, so as a "word" matches some kind of requirement, you want to modify the attributes around the word to highlight then? – MadProgrammer Feb 06 '13 at 11:48
-
[Oracle tutorial](http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html) in the middle of the document (based on JTextArea, but doesn't matter, concept is the same, similair) – mKorbel Feb 06 '13 at 12:28
while the user types i want to delete the contents of JTextPane and insert a customized text instead.
this isn't job for DocumentListener, basically this Listener is designed to firing events out from JTextComponents to the another JComponent, to Swing GUI, implemented methods in used Java
have look at DocumentFilter, this provide desired methods to change, modify or update own Document (model for JTextComponents) on runtime

- 109,525
- 20
- 134
- 319
Wrap the code you call in SwingUtilities.invokeLater()

- 56,971
- 9
- 68
- 98
-
3This could lead to an infinate loop, where the user updates the document, then the program updates the document, then the program updates the document, then...:P – MadProgrammer Feb 06 '13 at 11:42
-
@MadProgrammer you can define flag or remove the listener and readd it after action is done. – StanislavL Feb 06 '13 at 12:07
-
heheheheheh `SO Forum` againts `King of JTextComponents`, I'm going to adopt, have to wait a see who wins :-) – mKorbel Feb 06 '13 at 12:16
-
-
-
@MadProgrammer here :-) Yeah, it _can_ be done, but is dirty enough to merit a downvote (Stan, you have been waiting for it, didn't you :-) - my problem is not the dirtyness as such, but dirtyness without need. – kleopatra Feb 06 '13 at 13:07
-
@kleopatra it's really my -1 for the dirty solution. Not sure how to avoid it e.g. when we have to replace abbreviation with full text. – StanislavL Feb 06 '13 at 13:12
-
3
-
1
-
1might be missing something but ... implement the filter's replace as needed? Taking your example of an abbreviation: find its start, change the offset to that and adjust the replacement length and change the text to the full word. – kleopatra Feb 06 '13 at 14:09
-
Ok, May be you are right in the case. Another example then. Imagine a table in the beginning of the document. User hits ENTER. MS WOrd creates a paragraph _before_ the table (not in the first cell). That requires first processing the user typings and then restructure DOM hierarhy elements (moving the paragraph top be before the table). It can't be done in the filter. And I don't think my solution is hack. 1. We detect some condition in the listener 2. we start some action _after_ the original change 3. we prevent unnecessary event triggering. What's wrong with this? – StanislavL Feb 07 '13 at 05:59