tags:

views:

457

answers:

2

I'm currently working on a hobby project, written in Java, containing about two different JFrames with about 3-4 JPanels each. The problem I'm facing is that I'm not so sure how to handle the interaction with my controller and different view classes.

For instance, I've an article by Sun on Java App. design with MVC, where they list the option to let all the communications between model and view go through the controller as the most modern one, a tactic I've been taught as well and should do just fine. However, it doesn't quite go as deep as to explain how to handle all the ActionListeners involved for all the elements and different panels.

The 'way to go' I've been taught so far is to either use one controller and set the ActionListener to the various objects through getters and keep track of the active panel. The alternative my awesome Java book gives is to just stick to inner classes for each view class. Either method seems to result in pretty nasty code, while I'd prefer one or several controllers with as little bloat as possible.

My question of course is; how would you assign the ActionListeners as neatly and efficiently as possible while keeping the controller(s) usable?

A: 

The controller can implement ActionListener and contains a List of ActionListeners.

The controller you have to add to the The 3-4 top panels action listener. Now you can add any ActionListener you want to the controller action listener list.

public void addListener(ActionListener listener)
{
   mActionListeners.add(listener);
}

public void removeListener(ActionListener listener)
{
   mActionListeners.remove(listener);
}

When the controller Action listener is called you have to call all action listener which are inside the controll list.

public void actionPerformed(ActionEvent e) {
   List listeners = mActionListeners; // Edit 20090903
   for (Iterator iterator = listeners .iterator(); iterator.hasNext();) {
    ActionListener actionListener = (ActionListener)iterator.next();
    actionListener.actionPerformed(e);
   }
}
Markus Lausberg
Thanks a lot, that probably the most elegant solution I've seen so far and potentially will. Much appreciated.
Leftblank
dont mention it. when you find a better solution please post it here and let me know.
Markus Lausberg
I'm not sure if you're also notified when it's a followup answer instead of comment, so here we go ;)
Leftblank
+2  A: 

Even though Markus' solution remains the neatest I've seen so far, I've made some slight changes, which are hopefully improvements in the eyes of the original author as well ;).

In case you add/remove an item of the list in response to an event, there is a chance of ending up with concurrent changes to the list; the event is handled, but the loop will continue in case there are more items after the one catching the event.

Therefore it's required to use a slightly different approach. I've decided to use the ListIterator.add() method, as this one supports modifications to the list while walking through its items. Possibly there are more elegant solutions available, but this one does the job pretty decent.

In case it will be of help to others; the modified code would similar be the following:

ListIterator<ActionListener> iterator = mActionListeners.listIterator();

public void actionPerformed(ActionEvent e)
{
 iterator = mActionListeners.listIterator();
 while (iterator.hasNext()) 
 {
  ActionListener actionListener = (ActionListener)iterator.next();
  actionListener.actionPerformed(e);
 }
}

public void addListener(ActionListener listener)
{
 iterator.add(listener);
}

public void removeListener(ActionListener listener)
{
 iterator.remove(listener);
}

In case there are better solutions or improvements I'll be glad to hear those as well.

Leftblank