Skip to main content

JTextPane and paintComponent override

2 replies [Last post]
Joined: 2003-06-10
Points: 0

afternoon folk,
i have an rtf document rendered in a JTextPane. within the document are a couple of keywords that i want to have a visual highlight applied to (a line drawn just above them across the text area width. i am trying to come up with the best solution for this, as the document is an editable document, and hence the content either before or after the keywords will change, and the highlight must also change with it. i have about gotten it by tracking changes to the document, and tracking the line (relative to the start of the document) that the keyword is located in. my problem is two-fold. one is i can't seem to get the proper location offsets for using the draw Graphics2D.draw() method invocation. a code snippet of how i'm locating the offset in the text buffer, and then converting it to what i had hoped would be the proper coordinate space is as follows:
int yMarker0 = 0;
int yMarker1 = 0;

DefaultStyledDocument doc = (DefaultStyledDocument) editor.getDocument();
Style defaultStyle = doc.getStyle("default");
Font f = new Font(StyleConstants.getFontFamily(defaultStyle),
Font.PLAIN, StyleConstants.getFontSize(defaultStyle));
FontMetrics fm = editor.getFontMetrics(f);
try {
String[] nlCount = editor.getDocument().getText(0, editor.getDocument().getLength()).split("\n");
for(int i = 0; i < nlCount.length; i += 1) {
if(nlCount[i].contains("keyword0")) {
yMarker0 = i * fm.getHeight();
System.out.println("keyword0 on line " + i + " line height = " + fm.getHeight() + " data: " + nlCount[i]);
if(nlCount[i].contains("keyword1")) {
yMarker1 = i * fm.getHeight();
System.out.println("keyword1 on line " + i + " line height = " + fm.getHeight() + " data: " + nlCount[i]);
} else {
System.out.println("Skipping " + i + ":" + nlCount[i]);
System.out.println("yMarker0 = " + yMarker0 + " yMarker1 = " + yMarker1);
} catch (BadLocationException e) {


JEditorPane editor = new JEditorPane(){
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Line2D.Float(0, yMarker0, super.getWidth(), yMarker0));
g2.draw(new Line2D.Float(0, yMarker1, super.getWidth(), yMarker1));

when i hit the paintComponent(), the lines don't show up at the line the keywords are on, but rather much higher up (toward the top) in the document. the line numbers that are being displayed in the println calls are the correct line numbers though, and the font metrics seems to be correct. this feels like i'm fixing to have one of those duh moments once i hear what i'm doing wrong (or i happen to stumble across it).

the bigger problem is that i've spent about 12 hours searching and hunting for the proper way to accomplish this (the time spent isn't the problem), but i'm not sure i am really approaching it properly. i am might weak in swing programming, and i have wondered if i shouldn't be pursuing the swing highlighters route as a better approach, but even there, i'm not sure.

any help/suggestions would be appreciated as always.


Message was edited by: tjansto

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2004-03-04
Points: 0
Joined: 2004-05-26
Points: 0

I would not highlight text via paintComponent override. There is support for character/text manipulation in document views/renderers. Once I had to solve similar problem and ended up writing my own ParagraphView (or BoxView or some other view ... don't remember exactly) and parsing the document and setting character attributes which worked quite nicely. There were some minor issues like if highlight started in middle of the word, new character attribute group confused algorithm for line wrapping and it was breaking the word at the highlight boundary, but this could have been dealt with if needed as well (manually controlling the line break markers). I can try to dig out that code and make some small demo out of it if that sounds interesting, but it would take few days ...