February 28, 2021
Hot Topics:

Understanding Action Objects in Java

  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

The Action interface

According to Sun,

"The Action interface provides a useful extension to the ActionListener interface in cases where the same functionality may be accessed by several controls."
Previous sections in this article have discussed how such a capability may be used.

Here is a quotation from John Zukowski, which may help to illuminate the purpose of the Action interface.

"The Action interface is an extension to the ActionListener interface that's very flexible for defining shared event handlers independent of the components that act as the triggering agents. ..., the interface implements ActionListener and defines a lookup table data structure whose keys act as bound properties. Then, when an Action is associated with a component, these display properties are automatically carried over to it."
The actionPerformed method and other things

Because the Action interface extends the ActionListener interface, it declares the actionPerformed method.  In addition, this interface makes it possible to define the following items in a single location:

  • Text strings that describe the properties of action-aware components associated with an Action object.
  • Icons that may be displayed on action-aware components associated with an Action object.
  • The enabled/disabled state that should be tracked by action-aware components registered as PropertyChange listeners on an Action object
The enabled/disabled state

In addition to the actionPerformed method inherited from the ActionListener interface, the Action interface declares six methods in support of the functionality described above.

The two methods shown in Figure 7 are the standard JavaBeans setter and getter methods for the enabled property.

isEnabled() - Returns the enabled state of the Action.

setEnabled(boolean b) - Sets the enabled state of the Action.

Figure 7

Although it isn't obvious in the method declarations, the enabled property is a bound property as described earlier in this article. (In fact, the word bound doesn't appear anywhere in the JavaDocs description of javax.swing Interface Action for Java 2 Platform SE v1.4.0.)

PropertyChangeListener registration

The two methods shown in Figure 8 are the standard JavaBeans methods for registering and unregistering a PropertyChangeListener object.

addPropertyChangeListener(PropertyChangeListener listener) - Adds a PropertyChange listener.

removePropertyChangeListener(PropertyChangeListener listener)- Removes a PropertyChange listener.

Figure 8

All objects that are registered as a PropertyChangeListener on the Action object are notified when the value of any bound property changes.

Keyed properties

The two methods shown in Figure 9 are used to put and get the values of properties that I will refer to as keyed properties.  These methods behave like typical put and get methods for a hashtable object.

void putValue(String key, Object value) - Sets one of this object's properties using the associated key.

Object getValue(String key) - Gets one of this object's properties using the associated key.

Figure 9

The values of these properties consist of:

  • Text strings that describe the properties of action-aware components associated with an Action object
  • References to ImageIcon objects that may be displayed on action-aware components associated with an Action object.
The keys

The keys associated with these values are declared by the Action interface as public static final fields of type String, having the following names and purposes.

  • NAME - Used for storing the name for the action.  Appears at text on the face of a tool bar button or a menu item.
  • SHORT_DESCRIPTION - Used for storing a short description for the action.  This description is used for tooltip text.
  • SMALL_ICON - Used for storing a small icon for the action.  This icon appears on toolbar buttons and menu items.
  • ACCELERATOR_KEY - Used for storing a KeyStroke to be used as the accelerator for the action.
  • MNEMONIC_KEY - Used for storing a key code used as the mnemonic for the action.
  • ACTION_COMMAND_KEY - Used to determine the command string for an ActionEvent object.
  • DEFAULT - Can be used as the storage-retrieval key when setting or getting one of this object's properties.
  • LONG_DESCRIPTION - Used for storing a longer description for the action.
The key values

Because these fields are declared in an interface, they are inherently final.  They are all references to String objects.  Although the documentation doesn't specify the values encapsulated in the String objects, it can be determined experimentally that as of version 1.4.0, the string values encapsulated in the String objects are:

  • Name
  • ShortDescription
  • SmallIcon
  • AcceleratorKey
  • MnemonicKey
  • ActionCommandKey
  • Default
  • LongDescription
Whenever possible you should refer to the constants symbolically (as in Action.NAME) and avoid using the encapsulated values explicitly.  That way, if the encapsulated values change in some later version of Java, it will be less likely that your code will become broken.

Key-value pairs

The values associated with these keys (in a key-value pair sense) in any particular program are dependent on the program.  You will see how some of these keys are used in the sample program to be discussed later, so I won't discuss them further at this time.

Keyed properties are bound properties

Apparently each of these keyed properties behaves like a bound property; meaning that all registered PropertyChangeListener objects are notified whenever the value of one of these properties changes.  Whether or not that listener object takes any specific action as a result of the change is determined by the author of the class from which the PropertyChangeListener object is instantiated.

Implementing the Action interface

As is usually the case, you can start from scratch and define a new class that implements the Action interface.  Among other things, this will require you to provide PropertyChange support.

If you elect to take this route, I recommend that you consider using an object instantiated from the PropertyChangeSupport class or the SwingPropertyChangeSupport class to handle the registration and notification of PropertyChangeListener objects.

However, in most cases, you won't need to start from scratch.  Rather, you can define a new class that extends the AbstractAction class, and override any methods whose behavior needs to be different from that defined in that class.

The AbstractAction class

According to Sun,

"This class provides default implementations for the JFC Action interface. Standard behaviors like the get and set methods for Action object properties (icon, text, and enabled) are defined here. The developer need only subclass this abstract class and define the actionPerformed method."
Often, by extending this class, instead of defining a new class that implements the Action interface, you can save yourself a lot of programming effort.
(As a side note regarding the importance of the Action interface, more than two-dozen classes in v1.4.0 extend the AbstractAction class.)
Fields of AbstractAction class

In addition to the final fields inherited from the Action interface, this class defines the following two fields:

  • SwingPropertyChangeSupport changeSupport
  • boolean enabled
The first field contains a reference to an object instantiated from the SwingPropertyChangeSupport class.  As I mentioned earlier, this is a helper class designed to register and notify PropertyChange listeners

The second field is of type boolean, and specifies whether the action is enabled at a particular point in time.  The default value is true.

Methods of AbstractAction class

The AbstractAction class provides default implementations for each of the six methods declared in the Action interface (See Figures 7, 8, and 9.)

In addition, the AbstractAction class defines the four methods shown in Figure 10.

clone() - Clones the abstract action.

firePropertyChange(String propertyName, Object oldValue, Object newValue) - Supports reporting bound property changes.

getKeys() - Returns an array of Objects which are keys for which values have been set for this AbstractAction, or null if no keys have values set.

getPropertyChangeListeners() - Returns an array of all the PropertyChangeListeners added to this AbstractAction with addPropertyChangeListener(). 

Figure 10

The behavior of the clone method should be self-explanatory.

firePropertyChange method

This method can be used in a subclass to fire a PropertyChange event.  When a PropertyChange event is fired, the SwingPropertyChangeSupport object will send the appropriate PropertyChangeEvent to all registered PropertyChangeListener objects.

Page 3 of 6

This article was originally published on May 29, 2002

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date