views:

108

answers:

2

I'm using some 3rd party AWT components in a desktop application. The component's layout is changed within the paint() method, and this causes some very strange behaviour. This appears to be fixed by adding the synchronized keyword to the paint() method, but is this a safe thing to do?

+1  A: 

The paint method should only be called within one thread, the Event Dispatch Thread, so there is no need to synchronize. I would imagine that the root of the problem lies in how the components are being used. Take a look at this link for some ideas around concurrency in the UI.

akf
Interesting. In my case, synchronizing definitely fixes issues, so clearly it's being called from more than one thread. I'll investigate where that might be occurring.
Alison
Other methods that are permitted to run in different threads could theoretically hold the same lock.
Tom Hawtin - tackline
@Tom very good point, and it explains why synchronizing paint() fixed the issue - things were happening in another synchronized thread which changed the layout mid-paint.
Alison
+3  A: 

It looks like the paint() method is called outside the event dispatch thread, which can indeed cause very strange behaviour, which is why it should never be done.

Instead of paint(), application code should only ever call repaint()

Michael Borgwardt
Thanks Michael. `paint(Graphics)` was being called from `update(Graphics)`. I changed `update()` so it now calls `repaint()` and it seems to work so far...
Alison
@Michael any idea if it's safe to call `repaint()` from `update(Graphics)`?
Alison
@Alison: calling repaint() is safe, as it basically just drops an event into the EDT queue, which is synchronized properly.
Michael Borgwardt
@Alison: But there's a different problem: calling paint() from update() should actually be OK, since update() itself should only run on the EDT. Is your code calling update() directly? You may want to read http://java.sun.com/products/jfc/tsc/articles/painting/index.html to make sure you understand how Swing/AWT components are supposed to work.
Michael Borgwardt
@Michael Thanks, will give it a read :)
Alison
@Michael From reading that link, it sounds like update shouldn't be overridden at all, and it certainly shouldn't be calling `repaint()` as that will just trigger another `update()`.
Alison
@Alison: According to the API doc of update(), it is intended to be overridden. But yes, it should not call repaint().
Michael Borgwardt