Well, here is a solution.
In short, you can subclass JLabel
to draw the highlight manually. Override the paintComponent
method to do the actual drawing and use FontMetrics
to calculate where the highlighted region should be drawn.
Here is that answer in excruciating detail:
Basically, you can make a subclass of JLabel
that can highlight stuff. I would do that like this; you may want to do it somewhat differently:
Add a method that tells the label which part to highlight. This could be something like this, assuming you just need one highlighted region:
public void highlightRegion(int start, int end) {
// Set some field to tell you where the highlight starts and ends...
}
If you need multiple regions, just have an ArrayList instead of a simple field. A method for dehighlighting would probably be useful too.
Now, you need to override the paintComponent
method of JLabel
. Here you need to do several discrete steps, which you may want to organize in different methods or something. For simplicity, I'll put it all in the paint method.
@Override
protected void paintComponent(Graphics g) {
...
First, you need to figure out the physical dimensions of the highlight, which you can do using the nice FontMetrics
class. Create the FontMetrics
class for the Font
you're using.
FontMetrics metrics = new FontMetrics(getFont());
Now you can get all the information you need to create a rectangle that will be the highlight. You'll need the starting position, the height and the width. To get this, you'll need two substrings of the JLabel
's text as follows:
String start = getText().substring(0, startOfHighlight);
String text = getText().substring(startOfHighlight, endOfHighlight);
//You may also need to account for some offsets here:
int startX = metrics.stringWidth(start);
int startY = 0; //You probably have some vertical offset to add here.
int length = metrics.stringWidth(text);
int height = metrics.getHeight();
Now you can draw the highlighted region before drawing the rest of the label:
g.fillRect(startX, startY, length, height);
super.paintComponent(g);
}
Of course, if you want the highlight to span multiple rows, that will require more work.
If you were wondering, I have actually written something like this before. On a whim, I decided to write my own text area type component from a JPanel
, and this was basically the way I handled highlighting. Reinventing the wheel may be stupid in an actual project, but it does teach you random stuff that may come in useful...