October 31, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Understanding Action Objects in Java

  • May 29, 2002
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Sets certain component properties

Another important result of setting the Action property on the action-aware component is that certain other properties belonging to the component are also set from the values encapsulated in the Action object.  The properties that get set may differ for different component classes.  For example, if the component is a JButton, the properties that get set include:

  • The enabled property
  • The property that controls the text on the face of the button
  • The property that controls the Icon that appears on the button
  • The text for the tool tip
  • The Mnemonic for the button
You can learn more about this process by taking a look at the documentation for the configurePropertiesFromAction method for the class of interest.  This is the method that handles the configuration process for each different component.
(Note that this documentation for version 1.4.0 is considerably different from the documentation for version 1.3.1 with respect to the AbstractButton, JButton, and JMenuItem classes.  In particular, the list of properties that get set has been expanded in all three cases.  I don't know if this is the result of changes, or earlier typographical errors.)
For example, here is what Sun has to say about the configurePropertiesFromAction method for the AbstractButton class (v 1.4.0):
"The properties which are set may differ for subclasses. By default, the properties which get set are Text, Icon, Enabled, ToolTipText, ActionCommand, and Mnemonic."
The Sun documentation for the configurePropertiesFromAction method for the JButton class says essentially the same thing as the documentation for the AbstractButton class.

In comparison, here is what Sun has to say about the configurePropertiesFromAction method for the JMenuItem class:

"By default, this method sets the same properties as AbstractButton.configurePropertiesFromAction(), plus Accelerator."
In other words, a JMenuItem object can set and track one property, Accelerator, which is not tracked by a JButton object.

PropertyChange notification

Earlier I stated that whenever an Action object is set or registered on an action-aware component, at least two important things happen.  I have been discussing the first of the two things that happen.  It is now time to discuss the second important thing that happens.

Setting the Action object on an action-aware component causes the component to be registered as a PropertyChange listener on the Action object.  Thereafter, whenever the value of the enabled property of the Action object changes, the component is notified of the change.

(It is the responsibility of the component to respond to that notification and to cause its enabled property to track the value of the enabled property of the Action object.)
Keyed properties

Certain other properties belonging to the Action object are also tracked and updated on the component as the Action object's keyed properties change.

(Disclaimer:  Even though I refer to these values as keyed properties, it is probably not technically correct to call them properties or bound properties, because the methods for setting and getting their values do not conform to the JavaBeans design patterns for properties.  However, they behave like bound properties, meaning that the component is notified when the values of the keyed properties change.)
A PropertyChangeListener

This update process is handled by causing the component to act like a PropertyChangeListener registered on the Action object.

(The components can't actually be PropertyChangeListeners in their own right, because they neither define nor inherit the method named PropertyChange.)
Some smoke and mirrors is being used here.  This process is handled by the method named createActionPropertyChangeListener.
(I'm not certain exactly how this is handled, but my guess is that the invocation of the setAction method on a particular component causes the invocation of the createActionPropertyChangeListener method on that component.  I suspect that this method instantiates an object from a class that implements the PropertyChangeListener interface.  This PropertyChangeListener object is registered on the Action object so that it is notified when a property change occurs.  My guess is that it also holds a reference to the component for which it was instantiated.  When it is notified of a PropertyChange event on the Action object, it updates the component's properties using current values from the Action object.  This causes the component to behave like a PropertyChangeListener.)


Overridden createActionPropertyChangeListener

Different overridden versions of the createActionPropertyChangeListener method exist for different component classes, so the properties that are tracked and updated may differ from one component class to the next.

For example, if the component is a JButton, the properties that are tracked and automatically updated include those in the following list:

  • The enabled property
  • The property that controls the text on the face of the button
  • The property that controls the Icon that appears on the button
  • The text for the tool tip
  • The Mnemonic for the button
Notification mechanism

In typical fashion, the propertyChange method shown in Figure 2 is invoked on every registered listener when the Action object fires a PropertyChange event.
 

public void propertyChange(PropertyChangeEvent evt)

This method gets called when a bound property is changed.

Parameters:
evt - A PropertyChangeEvent object describing the 
event source and the property that has changed.

Figure 2

It is the responsibility of the propertyChange method in each registered listener object to use this notification to cause the enabled state of the component to track the value of the enabled property of the Action object.  This method also causes other properties discussed above to track the values of the corresponding keyed properties of the Action object.

Two different programming styles

Two different programming styles can be used to accomplish the above behavior.  The first of those programming styles existed prior to the release of JDK 1.3.  The second approach was released with JDK 1.3 and updated in JDK 1.4.0.

The earlier approach, (which is still supported in version 1.4.0 but is not the preferred approach), makes use of a specialized version of the add method for three specific container types:  JMenu, JPopupMenu, and JToolBar(This method is limited to use with those three container types).  The signature of the specialized version of the add method for each of the three container types respectively is:

  • public JMenuItem add(Action a)
  • public JMenuItem add(Action a)
  • public JButton   add(Action a)
The specialized add method

This specialized version of the add method is defined for the container classes JMenu, JPopupMenu, and JToolBar.  Here are descriptions for this method as defined for those three classes respectively:

  • JMenu - Creates a new menu item attached to the specified Action object and appends it to the end of this menu.  Returns JMenuItem.
  • JPopupMenu - Appends a new menu item to the end of the menu, which dispatches the specified Action object.  Returns JMenuItem.
  • JToolBar - Adds a new JButton, which dispatches the action.  Returns JButton.
Not the preferred method

Although this method is still supported as of JDK 1.4.0, in all three cases, Sun has something like the following to say:

As of JDK 1.3, this is no longer the preferred method for adding Actions to a container. Instead it is recommended to configure a control with an action using setAction, and then add that control directly to the Container.
However ...

Even though this is not the preferred approach, you are very likely to encounter code that uses this approach.  Therefore, I am providing a brief description of this approach, and will compare it with the preferred approach.

(All of the discussion, from the beginning of the article down to the beginning of the above discussion on the specialized add method, was based on the preferred approach.)
Use is restricted to three container types

It is important to emphasize that this approach can only be used with the following container classes (because other container classes neither define nor inherit the specialized version of the add method):

  • JMenu
  • JPopupMenu
  • JToolBar
The preferred method, on the other hand, can be used with just about any of the standard container classes.
(For example, you could place an action-aware component in a JButton if you had a reason to do so.  However, you may want to avoid using AWT container classes in order to avoid the problems inherent in mixing heavyweight and lightweight components.)
The specialized add method

When the specialized add method is invoked on one of the three containers listed above, passing an Action object as a parameter, the following things happen:

  • The container creates a component that is appropriate for that container:
    • JMenu creates a JMenuItem
    • JPopupMenu creates a JMenuItem
    • JToolBar creates a JButton
  • The container gets the appropriate properties (such as enabled and the icon) from the Action object to customize the component.
  • The container checks the initial state of the Action object to determine if it is enabled or disabled, and renders the component in the same state.
  • The container registers a PropertyChangeListener with the Action object so that it is notified of state changes. When the Action object changes from enabled to disabled, or back, the container makes the appropriate revisions and renders the component accordingly.
The major differences

The major differences between this approach and the preferred approach seem to be:

  • This approach is limited to only three types of containers, whereas the preferred approach can be used with just about any container.
  • This approach can only be used with one specific component type for each of the three containers.  The preferred approach can pair any of a large number of component types with just about any container.
Much more general

The bottom line is that the preferred approach is the more general of the two.  For example, if you had a reason to do so, you could put an action-aware JTextField object in a JMenu object, or an action-aware JRadioButton object in a JButton object.

A sample program

Now it is time to take a look at some code.  A complete listing of the sample program named ActionObj02 is shown in Listing 22 near the end of this article.

This program uses the preferred approach to place two action-aware components in each of the following three container types:  JMenu, JToolBar, and JPanel.

(Note that the earlier approach did not support the JPanel container type.)
Two different Action objects are used to populate the three containers.  Within each container, one of the components is registered with one of the Action objects, and the other component is registered with the other Action object.

The JMenu container is populated with two JMenuItem objects.  The JToolBar container is populated with two JButton objects.  The JPanel container is populated with one JButton object and one JMenuItem object.

View at startup

Figure 3 shows a view of the program as it appears at startup (the JMenu object is hidden from view).

Figure 3 View of Program at Startup

The title for the hidden menu is shown at the top in Figure 3.  A tool bar object is shown immediately below the menu bar.  A JPanel object is shown at the bottom.

The four checkboxes in the center are used to manipulate the enabled and icon properties of the two Action objects.  This, in turn, causes the enabled property of each of the components to change, and also causes the icon displayed on each of the components to change, when the checkboxes are checked and cleared.

The expanded menu

Figure 4 shows the screen display of the program with the menu expanded, but with no other changes.

Figure 4 View with Menu Expanded

As you can see, the two menu items represent the same Action objects as the components on the tool bar and the components in the JPanel.

Manipulating the Action objects

The checkboxes in the center can be used to manipulate the Action objects.  For example, Figure 5 shows the output with one of the Action objects disabled by checking the upper-left checkbox.  (Note that the text on the checkbox also changes when it is checked.)

Figure 5 View with One Action Item Disabled

As you can see in Figure 5, disabling one of the Action objects causes both of the visible action-aware components registered (as PropertyChange listeners) on that object to be disabled.

(The menu also contains a component registered as a PropertyChange listener on that Action object.  If you could see that component, you would see that it is disabled also.)
In a similar fashion, checking the upper-right checkbox would disable the other Action object and the three components registered as PropertyChange listeners on it.

Toggle between two icons

The enabled property is clearly a property in the sense that its setter and getter methods match the JavaBeans design pattern for properties.

As we will see later, the property that specifies the icon to be displayed on the components doesn't use the standard setter and getter methods for properties.  Regardless, changing the property that specifies the icon in the Action object causes the components registered on that object to display a different icon.

Figure 6 shows the result of checking the lower-left checkbox.  Checking and clearing this checkbox toggles the specified icon in the Action object between two different gif files.

Figure 6 View with a Different Icon

As you can see in Figure 6, changing the property that specifies the icon in one of the Action objects causes the icon displayed on registered components to change from a red ball to a blue ball.  Again, if you could see the corresponding item on the menu, you would see that it has changed also.



Page 2 of 6



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel