Normally there are two standard ways to implement the ActionListener interface: The first is to let a class implement the ActionListener interface and then add an object of this class to the addActionListener methods of the components firing ActionEvents. You then have to check the source in the actionPerformed method. You end up with a big ugly, unmaintainable and unstable if-then-else- statement. The second approach is to define a class for every such component. You end up with tons of small classes all increasing the memory footprint (typically 3K per class).
Now this approach using reflection lets you define a method for each such component avoiding the mentioned drawbacks and has the following advantages:
Although there are no compile time errors if the specified method doesn't exist, you don't have to wait for the method to be called to get an Exception. The constructor will already throw a NoSuchMethodException in that case.
Reflective actions are heavily used and supported throughout the whole Extended Action Framework.
The XActions class is a utility class providing convenience methods, which are described in this section.
Let's first have a look at the configureButton method:
This method configures an AbstractButton with an XAction. It can be specified, which icon type should be use (small icons, large icons or no icons), if the text should be displayed and if the buttons should have a cool style. If cool style is set to true, then the border of the button will be drawn only if the mouse pointer is over the button. Note: Since Java 1.4 you can create a similar effect by setting the rollover property of the toolbar to true. However look and feels may ignore this property and the Java Look and Feel does so.public static void configureButton(AbstractButton button, XAction action, IconType iconType, boolean showText, boolean coolStyle)
Like this you can first specify all information in one XAction object and then specify which data should be displayed using this same XAction object.
Try this:Note: This sample uses the GeneralActionFactory class, which will be discussed later in the section The Standard Action Factories.
- using Java Web Start.
- This sample shows 1 menu and 2 toolbars all configured by the same XAction objects.
Source code: ConfigureButtonsSample.java
The configureButton method is twice overloaded:
The first variant additionally adds the button to a ButtonGroup. The second variant registers an ItemListener to the button.public static void configureButton(AbstractButton button, XAction action, ButtonGroup group, IconType iconType, boolean showText, boolean coolStyle) public static void configureButton(AbstractButton button, XAction action, ItemListener listener, IconType iconType, boolean showText, boolean coolStyle)
Instead of first creating a button and then configuring it using one of the methods discussed above, the XAcions class also provides convenience methods to create such configured buttons directly:
With these methods the previous sample could be rewritten like this:public static JButton createButton(XAction action, IconType iconType, boolean showText, boolean coolStyle) public static JCheckBox createCheckBox(XAction action, ItemListener listener, IconType iconType, boolean showText) public static JCheckBoxMenuItem createCheckBoxMenuItem(XAction action, ItemListener listener, IconType iconType, boolean showText) public static JMenuItem createMenuItem(XAction action, IconType iconType, boolean showText) public static JRadioButton createRadioButton(XAction action, ButtonGroup group, IconType iconType, boolean showText) public static JRadioButtonMenuItem createRadioButtonMenuItem(XAction action, ButtonGroup group, IconType iconType, boolean showText) public static JToggleButton createToggleButton(XAction action, ButtonGroup group, IconType iconType, boolean showText, boolean coolStyle) public static JToggleButton createToggleButton(XAction action, ItemListener listener, IconType iconType, boolean showText, boolean coolStyle)
The modified source code: CreateButtonsSample.java
The XActions class provides the following utility method to configure a XAction object from a ResourceBundle:
This method is looking for the following keys:public static void configureXAction(XAction action, String name, ResourceBundle rb)
Key Value <name>.name The Name to be Displayed <name>.shortDescription Tool Tip <name>.acceleratorKey Shortcut <name>.mnemonicKey Mnemonic <name>.largeDisabledIcon File Name <name>.largeDisabledSelectedIcon File Name <name>.largeIcon File Name <name>.largePressedIcon File Name <name>.largeRolloverIcon File Name <name>.largeRolloverSelectedIcon File Name <name>.largeSelectedIcon File Name <name>.smallDisabledIcon File Name <name>.smallDisabledSelectedIcon File Name <name>.smallIcon File Name <name>.smallPressedIcon File Name <name>.smallRolloverIcon File Name <name>.smallRolloverSelectedIcon File Name <name>.smallSelectedIcon File Name
If a key is not specified it in the ResourceBundle it will be ignored!myAction.name = MyAction myAction.shortDescription = My Action myAction.acceleratorKey = Control M myAction.mnemonicKey = A myAction.largeIcon = /myGraphics/MyAction24.gif myAction.smallIcon = /myGraphics/MyAction16.gif
Instead of first creating a XAction object and then configuring it using configureXAction method discussed above, the XAcions class also provides a convenience method to create such a configured XAction object directly:
This method will create a ReflectiveXAction. (See the Reflective Actions section to learn more about reflective actions.) The object 'target' is expected to have a method:public static XAction createXAction(String name, Object target, ResourceBundle rb) throws NoSuchMethodException
public void <name>(ActionEvent e)
The Standard Action Factories provide utility methods to create and configure XActions for standard actions. However they do not provide any functionality for the actions since that is application specific.
All Standard Action Factory classes are typesafe enums, which provide one action factory instance for each supported standard action. They all derive from the base class StandardActionFactory. The StandardActionFactory provides two methods:
Note: The createXAction-method expects that the object 'target' has a method:public XAction createXAction(Object target, Locale locale) throws NoSuchMethodException public void configureXAction(XAction action, Locale locale)
where <name> is equal to the output of the toString()-method of the action factory.public void <name>(ActionEvent e)
E.g. to create the standard action "save" you could use:
or:
The data in the resource bundles that backup the Standard Action Factories is based on the following sources:
There is one Standard Action Factory class for each part of the Java Look and Feel Graphics Repository:
The follwing sample provides an overview over what data is already available.
Try this:
- using Java Web Start.
- This sample shows 1 menu and 1 toolbar for each Standard Action Factory class.
(Except the GeneralActionFactory class for which there are 2 toolbars.)Source code: StandardActionFactoriesSample.java
From the source code: