Stephane Grenier
Stephane Grenier

Reputation: 15927

Who is calling paintComponent?

For some reason, my paintComponent(Graphics g) method is being called infinitely. I can't seem to tell who is calling it, even if I dump a StackTrace in the call (it's an event that's dispatched and handled).

Are there any easy ways to find out who's triggering the event?

Update: I've found the cause and I now understand the reason. Whoever answers it correctly will get the answer to the question.

Here is the code that's causing the issue:

@Override
public void paintComponent(Graphics g)
{
    myJButton.setIcon(ResourceLoader.getImageIconWithLocale(MY_BUTTON_IMAGE));
    super.paintComponent(g);
}

FYI: It's a really tricky one!! It's not obvious by looking at the code. I made an assumption that was wrong.

Upvotes: 4

Views: 530

Answers (4)

Stephane Grenier
Stephane Grenier

Reputation: 15927

The setIcon(ImageIcon) will revalidate and repaint itself ONLY if the ImageIcon is another instance.

When working with Locales, most people are use to the ResourceBundle, which returns Strings, which in turn are immutable. Therefore setting the text over and over doesn't matter.

However, in this case, the ResourceLoader (custom class) returned a new instance of an ImageIcon. Sure it was the same Image, but it was another instance. And if you decompile the code, you'll see that setIcon (at least for JButtons), it will repaint and revalidate if newIcon != oldIcon.

The solution was to use a HashMap in the ResourceLoader, this way it saves from loading the images more than once since most of the images are used very frequently (might as well reuse the instances if you can). Turns out that overall this quick adjustment also saved a decent amount of overall memory consumption as an added bonus.

Upvotes: 2

camickr
camickr

Reputation: 324118

The problem is that you are setting the icon in the paintComponent() method. You should never set a property in this method.

Swing components are smart enough to repaint themselves whenever a property changes. In this case you have the problem of the component repainting itself because the Icon changes, but you are also rereading the Icon every time the component repaints itself which is also not very efficient.

Upvotes: 0

locka
locka

Reputation: 6029

I don't know which component this is, but setting an icon on a button from within a paint routine is a bad idea. It will definitely cause the button to be repainted. If the button is a child of your component then setting the button invalidate the component too causing an infinite loop.

Set the icon somewhere else such as where the dialog / window is set up initially.

Upvotes: 2

Amir Afghani
Amir Afghani

Reputation: 38531

Are you calling repaint() anywhere? Also, when a window becomes visible (uncovered or deminimized) or is resized, the "system" automatically calls the paintComponent() method for all areas of the screen that have to be redrawn.

Upvotes: 0

Related Questions