I've been developing java programs for 1½ year. I'm currently working on a summer project, that involves quite a big Graphical User Interface.
My GUI consists of several tabbed panes. Each pane has its own class. Each pane has SEVERAL jButtons.
Now, I've come to a point, where there's so many anonymous inner classes (for ActionListeners) in my tabbed-pane classes, that I am certain there must be a better way; if not for efficiency, then for maintainability - it's becoming quite a mess.
My question is this: Is there a better to organize listeners, when you have a lot of them in each class? I've thought about clustering the listeners in relevant classes - like the following sample code:
public class SomeListeners implements ActionListener{
@Override
public void actionPerformed(ActionEvent e){
String command = e.getActionCommand();
switch(command){
case "This button":
doThis();
break;
case "That button":
doThat();
break;
}
}
}
Or might there be an even better way?
Thanks in advance :)
You could try the following approach:
Use real classes instead of anonymous classes. Every ListenerClass implements only one Use-Case / Functionality. The Classname should describe the UseCase. Then you can organize the classes in one or more packages to cluster them by categories that fit to the Use-Cases that the Listener in the package implements.
That means, you create an hierarchy of abstraction, that organizes the functionality like a tree-structure.
If some day later somebody has to maintain the Listeners he/she can find the Listener by first looking for a package that fits to the UseCase and then for the UseCase itself. Since you will have less packages then Classes it will be easier and faster to find the Listener.
Another way to think about that: If you have so much Events on one Tab, that you get problems organizing them in the code, how do you organize them visually on the Tab? Can you handle that in an ergonomic way for the user? Maybe the solution could be in splitting the functionality on more then one Tab? But since I don't know your UI I cannot say too much about that
I would recommand to use single class from type javax.swing.AbstractAction
Example:
Action leftAction = new LeftAction(); //LeftAction code is shown later
...
button = new JButton(leftAction)
...
menuItem = new JMenuItem(leftAction);
leftAction = new LeftAction("Go left", anIcon,
"This is the left button.",
new Integer(KeyEvent.VK_L));
...
class LeftAction extends AbstractAction {
public LeftAction(String text, ImageIcon icon,
String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e) {
displayResult("Action for first button/menu item", e);
}
}
Per duffymo: Use dependency injection and pass in the Listeners. This will give you the opportunity to reuse and change them at will.
Per me (hovercraft): It doesn't have to be Spring as Guice would work just fine. And it would work well with treeno's suggestion as well as Tim Herold's suggestion (1+ to them both). It's all about loosening coupling and tightening cohesion as best possible.
At some point, anonymous inner classes go from "convenient" to an evil mess. You have passed that point.
Like Tim, I suggest you use an AbstractAction. However, to expand, create your own abstract subclass that can read its name, icon, description (for tooltips) etc. from a configuration file. That way you can internationalize the code, and others (marketing) can easily change the buttons from "Save" to "SuperSomethingTM" or whatever. And the graphic artist can easily modify the icon. Extend this class for the actual implementation.
One added advantage of AbstractAction is that they can be disabled. So, if there are no changes to be saved, you can easily disable the Save menu, the Save button and the Save icon in the toolbar.
There are various ways to store and read this config info. One is a ResourceBundle.
(Typed on my Nook so this is on the short side, others feel free to expand)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With