Search code examples
javaswinggradientjtextfieldpaintcomponent

Gradient textfields in panel with TitledBorder - performance issue


I have a panel with 3 inner panels that all use a TitledBorder. The third inner panel has a number of custom textfields that are painted with GradientPaint. The textfields come from a custom class that extends JTextField and uses an overriden paintComponent method along with a MouseListener, so that when mouse enters on a textfield area the gradient color slightly changes (and changes back again when mouse leaves the textfield).

The problem is that the gradient color change does not perform very well when those textfields are inside a panel with a TitledBorder (which by the way is a compound border). I mean that they do not respond fast enough, but they respond well when they're not in such a panel (I've tested this).

I thought that the problem is the border itself, so I tried to override the TitledBorder's paintBorder() method where I added a print statement whenever this method is called to draw the border... and it seems that every time the mouse enters a textfield's area (and the gradient color changes) the TitledBorder is painted again. If I quickly move the mouse pointer across all the textfields (they're just 4 of them) then the textfields are painted again (which is normal) but the compound TitledBorder is also painted every time and I guess that this causes the performance issue.

My question is simple, is there any way that I can tell Java NOT to paint again the panel's TitledBorder every time that the mouse moves on the panel's inner components?

I understand that this may cause problems sometimes, for example if I had a small titledbordered panel with a combobox: if I clicked on that combobox, the popup menu could hide part of the panel's border (provided that the combobox is close to the border's bottom side), so when the popup menu itself is hidden again the border should be painted again or else it would leave a "blank" area at the space where the popup menu and the border overlapped.

But in the previous case where the panel has only textfields and there is no need that the border should be painted again when the mouse moves at the panel's area, is it acceptable to prevent paintComponent() to be called and if yes, how? (or should I try something completely different that I didn't think of - sorry I'm not very experienced).

I can provide code of the gradient textfields paintComponent() method and the change that occurs on mouseEntered() but I thought that the problem's cause is clear and my assumption of why it occurs is right (correct me if I'm wrong)...

EDIT:

Ok while going through my custom classes trying to make the sscce I discovered my very stupid mistake. Instead of the standard TitledBorder I was using a CustomTitledBorder class that:

1) eliminated the 2 extra pixels added at the right side of the titled border 2) used a compound border and different font (palatino bold).

The problem was that the palatino font was not stored in memory but was read from the disk every time the constructor of my custom class was called. So it was also called every time paintBorder() was called. And so it was called every time the mouse moved over a textfield in the panel with the above border. This was very stupid, I'm sorry about this (and I was trying to figure out the performance problem for a day and more).

This does not answer my question though on how to avoid paintBorder to be executed every time the mouse is over a textfield, but it is not needed anymore (and I'm not really sure if it is acceptable anyway).


Solution

  • Cache the gradient in a BufferedImage, as shown here and here. Also consider TexturePaint, illustrated here.