Skip to main content

Changes to Actions in 1.6

Posted by zixle on November 21, 2005 at 8:16 AM PST

In my last two blogs I've covered various aspects of Actions. I had
originally wanted to write about the changes to Actions in 1.6 but
felt the background would make interesting blogs. I promise this is
the last blog on Actions for a while;)

In 1.6 we've overhauled Actions adding new features and fixing a
handful of annoying bugs. For this blog I'm going to cover the new
features and when you might use them.

Action.SELECTED_KEY

The single biggest request for Actions was to add support for Actions
to represent selected state. In particular when an Action is attached
to a JRadioButton, JCheckBox, JToggleButton and the like there was no
way to change the selected state of the component from the Action and
have it reflected in the component. The new key Action.SELECTED_KEY
takes care of that. All components that visually represent a selection
will now listen for changes to the SELECTED_KEY and reflect that in
the component.

The following code creates a JRadioButton from an Action that is
initially selected:

  Action action = new MyAction();
  // Make the action selected.
  action.putValue(Action.SELECTED_KEY, Boolean.TRUE);
  JRadioButton selectedRadioButton = new JRadioButton(action);

The SELECTED_KEY property is a bit different than other Action
properties. In particular the SELECTED_KEY property is both read and
set from the component; none of the other Action properties have this
characteristic. For example, if the user clicks on the radio button to
make it selected, the SELECTED_KEY property is set on the Action
from the component.

The following example shows how an Action could customize it's
behavior based on the selected state:

  class BoldAction implements Action {
    public void actionPerformed(ActionEvent e) {
      toggleBold((Boolean)getValue(Action.SELECTED_KEY));
    }
  }

Action.LARGE_ICON_KEY

All buttons and menu items have the ability to show an Icon. When a
button or menu item is associated with an Action the button or menu
item uses the Icon from the Action. This is problematic because
typically you want two different icons for these two components. To
address this in 1.6 we added LARGE_ICON_KEY. Menu items will only
use the Icon from the SMALL_ICON property. Buttons will first look for
the LARGE_ICON_KEY property, if it's value is non-null it will be
used, otherwise the value from SMALL_ICON is used. This enables you to
customize the Icon for the two different components.

The following example creates an Action with two different
icons. The menu item will use smallIcon and the button largeIcon:

  Action action = new MyAction();
  action.putValue(Action.SMALL_ICON, smallIcon);
  action.putValue(Action.LARGE_ICON_KEY, largeIcon);
  // menu item will use smallIcon
  new JMenuItem(action);
  // button will use largeIcon
  new JButton(action);

Note: the term button is a bit overloaded. AbstractButton is the
superclass of both menu items and classes such as JButton,
JToggleButton, JRadioButton ... In this context when referring to
button I mean all non JMenuItem subclasses that extend AbstractButton.

Action.DISPLAYED_MNEMONIC_INDEX_KEY

This is useful for the rare cases where you don't want the first
occurence of a character in the text to be underlined. For example,
a menu item with the text 'Save As' typically has the second 'a'
underlined. The following code shows how to do this:

  Action action = new MyAction();
  action.putValue(Action.NAME, "Save As");
  // Notice the autoboxing here.
  action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A);
  action.putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, 5);
  new JMenuItem(action);

Be careful when using DISPLAYED_MNEMONIC_INDEX_KEY. In particular if
you change the mnemonic you should be sure you change the
DISPLAYED_MNEMONIC_INDEX_KEY as well.

AbstractButton.setHideActionText

This property allows you to specify whether or not AbstractButton
should show the NAME property from the Action as the buttons
text. Consider if you have a menu item and toolbar button attached to
the same Action. To have non-empty text on the menu item the Action
will have a non-null value for it's NAME property. If you don't want
the toolbar button to show the text you would invoke
setHideActionText(true). The following code illustates this:

  Action action = new MyAction();
  action.putValue(Action.NAME, "Save As");
  new JMenuItem(action);
  JButton toolbarButton = new JButton(action);
  // We don't want the button to mirror the text from the Action.
  toolbarButton.setHideActionText(true);

System property swing.actions.reconfigureOnNull

The beans specification indicates that a null property
name can be used to indicate multiple values have changed. By default
Swing components that take an Action do not handle such a
change. To indicate that Swing should treat null
according to the beans specification set the system property
swing.actions.reconfigureOnNull to the
String value true.

This property is useful for cases where you want to do a bunch of
changes to an Action without sending individual property changes, and
then have all listeners refetch properties when done. I honestly can't
say I have ever had a need for this functionality, but it's now there.

The
javadoc for href="http://download.java.net/jdk6/docs/api/javax/swing/Action.html">Action
now details all this information as well as how the various components
support the different Action properties.

As usual, if you want to try out these changes (and the rest of the
goodness in 1.6) download the source and binaries from href="http://mustang.dev.java.net/">mustang snapshot release.

Related Topics >>