Java Tips Weblog

  • Blog Stats

    • 2,571,848 hits
  • Categories

  • Archives

Line Painter

Posted by Rob Camick on October 29, 2008

You have a text component that dislays multiple lines of text. Now you want to highlight the current line at the position of the caret. One possible way to do this might be to use a highlighter (as discussed in the last blog) and then adjust the highlight offsets whenever the caret changes location. The problem is that the default highlight painter will only highlight where text is painted. That is, the empty space to the right of the text is never highlighted. We want to highlight the entire line whether text goes to the end or not.

It won’t be a big change as we can still use the functionality of the highlighter to schedule the painting of highlights. So, we will add a dummy highlight to the text component that will use our custom painter. Now whenever the highlighter invokes our painter, we will simply ignore the Shape area passed to the painter and calculate our drawing area to be the entire width of the text component. We will still respect the height of the Shape area.

The LinePainter class can be used on any text component. You need to specify the text component to be highlighted so the various listeners used to track caret movement can be installed. In addition to painting the currently highlighted line, the LinePainter will be responsible for removing the highlight from the previous line. You also have the option to specify the line highlight color or use the default color. The default color will be calculated by using the existing text component selection color and then make it lighter. The color is made lighter by multiplying the RGB values of the selection color by a factor of 1.2.

The line painter in the image below was added by using:

LinePainter painter = new LinePainter(textPane);

Get The Code

LinePainter.java

See Also

Rectangle Painter

13 Responses to “Line Painter”

  1. Adam said

    Thanks Rob, very helpful and nice code.

  2. Mark said

    Awesome. It was one of the most well-written classes I ever found.

    It was easily customizable, it was easy to use, and it worked great!!!

    All I had to do was: LinePainter painter = new LinePainter(editor), and I got it! Thanks!!!

  3. Stefan said

    Hello,

    First of all, great class, very useful.

    I just have a question, how can i disable the line painter if I select some text?

    • Rob Camick said

      I don’t know how to disable the painter but text slection will still work. Just make sure the line painter color and the text selection color are different.

  4. Stefan said

    Thanks for the response.

  5. Anonymous said

    Thanks for the code!
    Problem: if I increment the caret in a loop line for line the painter sometimes does not reset the old line, so that multiple lines are highlighted. Could that be a thread issue? How could I solve this?

  6. Eng.Fouad said

    This is very helpful, thanks man :)

    There is one issue, whenever I change the font to Monospaced, it doesn’t work. Actually, the paint() method isn’t invoked. I change the font of the JTextPane as follows:

    editor.setFont(new Font(“Monospaced”, Font.PLAIN, 12));

  7. Anonymous said

    Hello Rob
    Thank you for placing this code in the public domain. I’ve included it in a small IDE that I am currently creating. It was working fine for a while, but I have now run into a very wierd issue with it. The method “resetHighlight” throws the following Exception:

    Exception in thread “AWT-EventQueue-0” javax.swing.text.StateInvariantError: GlyphView: Stale view: javax.swing.text.BadLocationException: Length must be positive

    The Exception occurs when the UndoManager undoes two “larger” changes in session. I’m inclined to believe it has something to do with how I am using the UndoManager, but all the documentation and tutorials suggest that I’m using it correctly … Do you have any idea why such an error might occur?

    • Rob Camick said

      I just noticed that the code does not work with the CompoundUndoManager presented in this blog as it appears the internals of undo processing have changed a bit in my JDK 11 version. I’ll have to look at that later.

      However, the LinePainter class still does work with the TextComponentDemo code found in: https://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html.

      Note I did have to make one small change:

      //private Rectangle lastView;
      private Rectangle lastView = new Rectangle(0, 0, 5, 5);
      

      So all I can suggest is to test with the demo code to see if it works. If it does, then I guess the problem is with your undo/redo implementation. Compare your code to the demo code.

Leave a comment