The last days I have been trying to implement a highlighting feature in a small text editor. For some reason I get a strange result:
The given example should highlight each "dolor" - the first occurences are correctly found and highlighted but the next ones aren't.
Here is the code I wrote so far:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
import javax.swing.text.DefaultStyledDocument;
/**
* Highlighting created on 04.11.2013<br>
* <br>
* Specification:<br>
*/
public class Highlighting extends JFrame implements MouseListener {
private JScrollPane scrollPane;
private JTextPane textPane;
private DefaultHighlighter highlighter;
private DefaultHighlightPainter painter;
public static void main(String[] args) {
new Highlighting().setVisible(true);
}
/**
*
*/
public Highlighting() {
this.initialize();
this.build();
this.configure();
}
/**
*
*/
public void initialize() {
this.scrollPane = new JScrollPane();
this.textPane = new JTextPane();
this.highlighter = new DefaultHighlighter();
this.painter = new DefaultHighlightPainter(Color.RED);
}
/**
*
*/
public void build() {
this.add(this.scrollPane);
}
/**
*
*/
public void configure() {
this.scrollPane.setViewportView(this.textPane);
this.textPane.setHighlighter(this.highlighter);
this.textPane.addMouseListener(this);
this.textPane.setDocument(new DefaultStyledDocument());
this.setPreferredSize(new Dimension(400, 500));
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
*
*/
private void highlight() {
this.highlighter.removeAllHighlights();
String selectedText = this.textPane.getSelectedText();
String text = this.textPane.getText();
int wordlength = selectedText.length();
int index = 0;
while ((index = text.indexOf(selectedText, index)) != -1) {
try {
this.highlighter.addHighlight(index, index + wordlength, this.painter);
} catch (BadLocationException e) {
e.printStackTrace();
}
index += wordlength;
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
this.highlight();
}
}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}
Does this has something to do with the line separators (\r\n
) ?
A
JTextComponent
'sgetText()
and AJTextPane/JEditorPane
'sgetText()
has different implementation.JTextPane/JEditorPane
usesEditorKit
to write the document content(text) to aStringWriter
and then return the text with formatting and inserting a line/paragraph break into the document. But theJTextCompoent
returns document content directly by:You will better understand if you try to compare the length :
jTextPane1.getText().length()
andjTextPane1().getDocument().getLength()
.Reproducing the difference in length by inserting string with:
So, in your high-lighting text program try reading the content text using:
Then search for your selected text position in the
contText
as you were doing and you should be good to go. Because,highlighter.addHighlight(int p0, int p1, Highlighter.HighlightPainter p)
uses thedocument
for position offset.Use
CaretListener
:To Highlight upon text selection, It is better to use
CaretListener
, no need to add mouse and key board selection handling code at all: