Run the following code and you'll see what the problem I encountered is. Indeed the line highlighting works well without using setCharacterAttributes(). How can I overcome the problem?
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
public class LineHighlighterEditor {
private static class LineHighlighter
extends DefaultHighlighter.DefaultHighlightPainter {
private JTextComponent textComponent;
private Highlighter highlighter;
private Object lastHighlight;
private Element root;
public LineHighlighter(JTextComponent textComponent, Color color) {
super(color);
this.textComponent = textComponent;
root = textComponent.getDocument().getDefaultRootElement();
highlighter = textComponent.getHighlighter();
addHighlight();
textComponent.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
removeHighlight();
addHighlight();
}
});
}
public Shape paintLayer(Graphics g, int o0, int o1, Shape s,
JTextComponent c, View v) {
try {
Rectangle r = c.modelToView(o0);
r.x = 0;
r.width = c.getSize().width;
g.setColor(getColor());
g.fillRect(r.x, r.y, r.width, r.height);
return r;
} catch (BadLocationException ex) {
ex.printStackTrace();
return null;
}
}
private void addHighlight() {
try {
int line = root.getElementIndex(textComponent.getCaretPosition());
int offset = root.getElement(line).getStartOffset();
lastHighlight = highlighter.addHighlight(offset, offset + 1, this);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
private void removeHighlight() {
highlighter.removeHighlight(lastHighlight);
}
}
public static void main(String[] arguments) {
JFrame pad = new JFrame("Line Highlighter Editor");
pad.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane editorPane = new JEditorPane();
pad.setContentPane(editorPane);
editorPane.setEditorKit(new StyledEditorKit());
new LineHighlighter(editorPane, Color.CYAN);
StyledDocument document = (StyledDocument) editorPane.getDocument();
editorPane.setText("1234");
document.setCharacterAttributes(0, 2, SimpleAttributeSet.EMPTY, false);
pad.setBounds(50, 50, 400, 300);
pad.setVisible(true);
}
}