Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

JFC actions

Use the powerful Command pattern with the JFC Action interface to build a reusable GUI-command library

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
The JFC Action interface provides a mechanism to detach application logic from GUI code. Unfortunately, Action implementations must usually be rewritten for each GUI, even if the action performs the same high-level operation. Fortunately though, through the careful use of interfaces and the Command pattern, it is possible to develop a library of reusable actions!

In this article, we will explore the Command pattern and JFC Actions. Using the JFC Action and Java interfaces, we will develop a library of commands that can be found in most applications. These commands include the File commands: New, Open, Save, Save As, Print, Close, and Exit; as well as the Edit commands: Cut, Copy, Paste, Delete, Select All, and Deselect all.

Actions 101: A primer

Java's JFC library provides an Action type. Actions are not visible components. Instead, an action encapsulates some GUI command and can take on a number of different graphical representations. In a typical GUI, an action can work behind the scenes to provide the logic for a button, menu item, or toolbar item. When created from an action, the component uses the action to obtain its string label, tooltip, icon, state, and ActionListener callback. Let's look at the javax.swing.Action interface:

public interface Action extends ActionListener
{
  public static final String DEFAULT = "Default";
  public static final String NAME = "Name";
  public static final String SHORT_DESCRIPTION = "ShortDescription";
  public static final String LONG_DESCRIPTION = "LongDescription";
  public static final String SMALL_ICON = "SmallIcon";
  public void addPropertyChangeListener(PropertyChangeListener listener);
  public Object getValue(String key);
  public boolean isEnabled();
  public void putValue(String key, Object value);
  public void removePropertyChangeListener(PropertyChangeListener listener);
  public void setEnabled(boolean b);
}


The class javax.swing.AbstractAction provides a basic action implementation. To create an action, we simply extend AbstractAction, provide the display information, and implement the action logic by defining the actionPerformed() method. Unless there is a compelling reason for you to reimplement the Action interface yourself, AbstractAction should suffice as an inheritable in most cases.

On the surface, actions may not seem very useful. However, they provide many benefits, which are listed below:

  1. Actions decentralize GUI logic by removing it from the GUI code entirely, thus simplifying the structure of GUI code immensely. Normally, one large actionPerformed() method contains all of the switch logic for each button and menu item in the window. In contrast, with actions we can avoid this switch nonsense by assigning an Action instance to each GUI construct. This is an approach that offers an elegant object-oriented alternative to the switch/case mess that generally exists in Java GUI code.
  2. Actions are not components. As a result, a single action may be shared among multiple GUI components. So, for example, a single action may have a menu representation and simultaneously appear in a toolbar. Instead of having to write the logic for the menu in one place and separate logic for the toolbar equivalent in another place, all logic resides in one centralized location.
  3. Actions simplify the creation of GUI constructs such as the menu item or toolbar button. To create a menu item or button, simply pass the action into the component's constructor. Once created this way, there is nothing else to do to wire the component to its callback, set its text label, or set its state -- the action handles all of these details.


Unfortunately, actions do not come without a price: the logic of the command is often mired inside the action itself. Actions tempt us to place all of the logic inside of the actionPerformed() method. Unfortunately, whenever something changes, you'll need to rewrite your actions. As a result, you can't easily take an action to another GUI. Instead, you are forced to constantly rewrite or extend the action portion of your code, even if these actions present the same command.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources
  • Source code resources
  • GUI Resources
  • The Pattern Languages of Program Design series
  • More pattern resources