| # Actions | Other Swing Changes

> ## API for Adding Actions to ActionEvent Sources

> ### Background

> Swing provides an implementation of the Command pattern which helps application developer centralize functionality which can be accessed from multiple places in the GUI. The `Action` interface is used to provide a stateful `ActionListener` which can provide the implementation of functionality accessed for example from the toolbar, a menu item, and a keyboard binding. As the state of the `Action` changes, for instance when it becomes disabled, the associated controls change their state accordingly (they also become disabled).

> ### The Problem

> For `Action`s to work as intended, the following connections need to be made (assume the `Action` has already been created):
> 1. The control needs to be created
> 2. The `Action` is added as an `ActionListener` on the control
> 3. A `PropertyChangeListener` is created which describes how the control should be updated in response to `PropertyChangeEvents` on the `Action`
> 4. The `PropertyChangeListener` is added as a listener on the `Action`.
> 5. Information about the linkage may need to be retained so it can be undone to allow garbage collection (in 1.2 this can be automatically handled with WeakRefs).
> Since a typical application may have between 5 and 25 `Action`s, and 2-3 controls per `Action`, the steps above need to be done up to 75 times!

> In order to relieve the developer of much of this burden, we have provided a way to have this done automatically, through helper methods on potential `Container`s of `Action`s. The three places where this is surfaced in Swing at present are:

> JToolBar.java | `public JButton add(Action a)`
> JMenu.java | `public JMenuItem add(Action a)`
> JPopupMenu.java | `public JMenuItem add(Action a)`

> The problems with this approach are several:

> 1. It is highly problematic for Builders, since it overloads `Container.add()` to allow a non-`Component` parameter which is not itself the thing that ends up being added.
> 2. Developers cannot participate in the configuration of the controls created without subclassing the container classes
> 3. Even if they do subclass, the granularity of the configuration ends up being per-`Container` instead of per-control added.
> 4. It limits developers to the expected control for each `Container` rather than allowing the full range of `ActionEvent` sources which `Action` permits.

> ### Solution

> Many developers have commented that they would prefer to create their own controls which are `ActionEvent` sources and then have a method which connects them to a particular `Action`. The solution is along these lines, and addresses the deficiencies listed above.

> The added API is initially added to AbstractButton, which defines the abstract superclass of `JButton, JMenuItem, JMenu, JCheckBox`, etc.

> The new public methods are as follows: ``

> - public void setAction(Action a)
> - public Action getAction()
> - protected void configurePropertiesFromAction(Action a)
> - protected PropertyChangeListener createActionPropertyChangeListener()
> In addition, constructors have been added to the ActionEvent sources which will allow for creating a control directly with the supplied Action.

> In JButton:

> `
> - public JButton(Action a)
> `
> Equivalent constructors have been added to:
> `
> - JCheckBox
> - JRadioButton
> - JToggleButton
> - JMenuItem
> - JMenu
> - JCheckBoxMenuItem
> - JRadioButtonMenuItem
> `
> Notes:
> - `setAction` is merely a helper method which performs the linkage steps described above as a convenience to the developer.
> - It is not expected that developers will often switch the `Action` for a control on the fly. However, it is possible for them to do so, using `setAction` since it replaces the previously set action and fires a `PropertyChangeEvent`.
> - This does not replace the standard method of adding `ActionListener`s, note that it uses `addActionListener()` as stated above
> - The current `Container` apis listed above will be reimplemented in terms of setAction, so that they give the same behavior as they did previously. This solution will make that code much easier to maintain!
> - The methods `configurePropertiesFromAction` and `createActionPropertyChangeListener` will be overridden in subclasses to provide the expected default behavior.

> ## createAction Factory Methods for JToolBar, JPopupMenu, JMenu

> New factory methods allow one to control what toolbars and menus create when an action is added directly, i.e. with the add method.

> Addition to JToolBar:

> `
> - protected JButton createActionComponent(Action a)
> `
> Addition to JPopupMenu:
> `
> - protected JMenuItem createActionComponent(Action a)
> `
> Addition to JMenu:
> `
> - protected JMenuItem createActionComponent(Action a)
> `

> ## New Action Constants

> See:
> `
> - public static final String ACCELERATOR_KEY
> - public static final String MNEMONIC_KEY
> `

> ## Add AbstractAction getKeys Method

> This new method is needed for serialization of Abstract Actions, and gives the developer a way to find out which keys have been set for the AbstractAction.

> See:

> `
> - public Object[] getKeys()
> `

Copyright © 1999 Sun Microsystems, Inc. All Rights Reserved. Please send comments to: swing-feedback@java.sun.com. This is not a subscription list. | Java Software