Search code examples
javaswinghighlightjtextpane

DefaultHighlightPainter keeps shifting in JTextPane


I am currently working on a application that reads a big text, and highlights a specific substring inside that text. And it kinda works...

But it seems that (and I have no clue why) the highligt keeps shifting every time it highlights the string.

public List<int[]> findString(String text) {        
    text = text.toLowerCase();

    List<int[]> highlightPositions = new ArrayList<int[]>();
    JTextPane pane = getTextPane();

    String paneText = pane.getText().toLowerCase();

    int end = 0;
    while (paneText.indexOf(text, end) != -1) {         

        int start = paneText.indexOf(text, end);
        end = start + text.length();        

        highlightPositions.add(new int[] {start, end});                 
    }

    try {
        highlight(highlightPositions);
    } catch (Exception ex) {
    }       
return null;
}

and this is the code that does the actual highlighting

public void highlight(List<int[]> highlightPositions) throws BadLocationException {
    DefaultHighlighter.DefaultHighlightPainter highlightPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);

    JTextPane textPane = getTextPane();     

    for (int[] position : highlightPositions) {
        System.out.println("Highlight: " + position[0] + " : " + position[1]);
        textPane.getHighlighter().addHighlight(position[0], position[1], highlightPainter);

    }
}

Does anyone know how to fix this?

EDIT: Here is how it looks when I attempt to highlight the word "Device".

Highlighting output


Solution

  • String paneText = pane.getText().toLowerCase();
    

    Don't use getText(). The getText() method will return the string with the end-of-line string for the platform which in the case of Windows is \r\n. However the Document only stores \n for the EOL string so you have a mismatch of offsets for every extra line in the Document.

    The solution is to use:

    String paneText = pane.getDocument().getText().toLowerCase();
    

    See Text and New Lines for more complete information on the problem.