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?
views:
108answers:
2
+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
2010-05-18 11:24:55
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
2010-05-18 11:26:25
Other methods that are permitted to run in different threads could theoretically hold the same lock.
Tom Hawtin - tackline
2010-05-18 11:28:32
@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
2010-05-18 16:32:30
+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
2010-05-18 11:28:28
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
2010-05-18 11:37:12
@Michael any idea if it's safe to call `repaint()` from `update(Graphics)`?
Alison
2010-05-18 14:06:15
@Alison: calling repaint() is safe, as it basically just drops an event into the EDT queue, which is synchronized properly.
Michael Borgwardt
2010-05-18 14:19:18
@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
2010-05-18 14:22:27
@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
2010-05-18 15:08:28
@Alison: According to the API doc of update(), it is intended to be overridden. But yes, it should not call repaint().
Michael Borgwardt
2010-05-18 18:47:37