views:

180

answers:

3

Hello!

I'm trying to write an own layout manager.

Components must be placed and sized relative to each other.
This means: when the user drags or resizes an component, some other components (but not the one altered manually by user) have to be altered.

Swing tells the layout manager to layout the components every time when some of them is moved/resized. This is a problem hence the layout manager itself moves/resizes components:
It fails, the method layoutContainer(Container parent) is called multiple times.

An example of the whole thing (simplified, in fact my layout manager does more complex stuff):

  • [-component1-][-component2-------][-component3-]
  • user resizes component2 to be smaller, my layout manager would adjust other components so that all of them would take same space as before:
    [-component1-][-component2-][-component3-------]
  • here, the actions should stop, but they go on: now the layout manager is invoked because of resizing component3

How could I achieve my intention (in an elegant way)?
Thank you.

EDIT:
Removed threading-related information after suggestions by answerers.

A: 

I can't speak to the correct implementation of a layout manager, but as far as threading is concerned, all events in Swing are dispatched on the Swing UI thread, i.e. the same thread. Thus, synchronizing objects will have no effect because only one thread is ever involved. You can see what thread is invoking a method by printing Thread.currentThread() or inspecting it in a debugger.

Depending on what you're trying to do, you may want to take a look at miglayout. I've found it very powerful and easy to use. Correctly implementing a Swing layout manager is a non-trivial task.

Dave Ray
Ok, I like to hear that Swing handles everything in one thread. But how to stop this snowball effect then? User-induced component movemets should be handled, automatic movement not.
ivan_ivanovich_ivanoff
+1  A: 

This isn't a thread synchronization issue.

You said that when users change the size or location of an object other objects must be altered. I'm guessing that you are listing for some kind of change event so that you can trigger a recalculation of the layout whenever the user changes an object. If so, I'm further guessing that your layout manager is triggering this event, causing it to be invoked again.

Of course, this is only speculation without reviewing your code.

Kris
I'm not listening events. The layoutmanager's "layoutContainer(Container parent)" is called by Swing when SOMETHING is moved.
ivan_ivanovich_ivanoff
somewhere you are listening to events, otherwise your components couldn't resize. Something the user is doing is resizing, so you musth ave a mouse listener or drag listener. You could trap mouse down, set a flag on your layout manager that the user is dragging, and clear the flag when you see mouse up. then you could differentiate between "user" changes (during drags) and "system" events. You could also capture this which component the user is actively modifying at the same place/time.
John Gardner
No, the layout manager's "layoutContainer(Container parent)" method is called (by Swing), after any component was moved/resized. That's it. Please believe me ;)
ivan_ivanovich_ivanoff
But thank you for the idea for setting the flag!
ivan_ivanovich_ivanoff
+2  A: 

This kind of feedback loop is not uncommon when dealing with events. There are several approaches you can use to break out of this loop and the one I suggest you try is to keep track of the calculated sizes of the components. Then, when you handle the resize event, compare the actual size to the calculated size, and just return without doing anything if they are equal. This is probably the most robust approach as it doesn't depend on the order or frequency of the events. As stated elsewhere you shouldn't need to touch anything related to threads from your layout manager.

CurtainDog
"Comparing the actual size to the calculated size" < it helped! Thank you very much.
ivan_ivanovich_ivanoff