If you have two or more components that perform the same function,
consider using an Action
object to
implement the function. An Action
object is an ActionListener
that provides not only
action-event handling, but also centralized handling of the text, icon, and
enabled state of tool
bar buttons or menu
items. By adding an Action
to a JToolBar
,
JMenu
, or JPopupMenu
, you get the following
features:
JButton
(for JToolBar
) or
JMenuItem
(for JMenu
and JPopupMenu
)
that is automatically added to the tool bar or menu. The button or menu item
automatically uses the icon and text specified by the Action
.
Action
object) for the
button or menu item.
Action
to create a
tool-bar button and menu item that perform the same function:
Action leftAction = new <a class that implements Action>(...); JButton button = toolBar.add(leftAction); JMenuItem menuItem = mainMenu.add(leftAction);
For a button or menu item to get the full benefit of using an
Action
, you must create the component using the
add(Action)
method of JToolBar
, JMenu
,
or JPopupMenu
. Currently, no API beyond
addActionListener(ActionListener)
exists to connect an
Action
to an already existing component. For example, although
you can add an Action
object as an action listener to any button,
the button won't be notified when the action is disabled.
To create an Action
object, you generally create a subclass of
AbstractAction
and then
instantiate it. In your subclass, you must implement the
actionPerformed
method to react appropriately when the action
event occurs. Here's an example of creating and instantiating an
AbstractAction
subclass:
leftAction = new AbstractAction("Go left", new ImageIcon("images/left.gif")) { public void actionPerformed(ActionEvent e) { displayResult("Action for first button/menu item", e); } };
Here's a picture of a demo application that uses actions to implement three features.
Here is what the user sees when the "Go left" action is disabled:
Try this:
- Compile and run the application. The source file is
ActionDemo.java
. You will also need three image files.
See Getting Started with Swing if you need help compiling or running this application.- Choose the top item from the left menu (Menu > Go left).
The text area displays some text identifying both the event source and the action listener that received the event.- Click the leftmost button in the tool bar.
The text area again displays information about the event. Note that although the source of the events is different, both events were detected by the same action listener: theAction
object with which the components were created.- Choose the top item from the Action State menu.
This disables the "Go left"Action
object, which in turn disables its associated menu item and button.
Here's the code that disables the "Go left" action:
After you create components using anboolean selected = ...//true if the action should be enabled; //false, otherwise leftAction.setEnabled(selected);
Action
,
you might well need to customize them. For example, you might want to set the
tool-tip text for a button. Or you might want to customize the appearance of
one of the components by adding or deleting the icon or text. For example, ActionDemo.java
has no icons in its menus, no
text in its buttons, and tool tips for its buttons. Here's the code that
accomplishes this:
button = toolBar.add(leftAction); button.setText(""); //an icon-only button button.setToolTipText("This is the left button"); menuItem = mainMenu.add(leftAction); menuItem.setIcon(null); //arbitrarily chose not to use icon in menu
The following tables list the commonly used Action
constructors and methods. The API for using Action
objects falls
into two categories:
Constructor or Method | Purpose |
---|---|
AbstractAction() |
Create an Action object. Through arguments, you can
specify the text and icon to be used in the components that the action
controls. |
void setEnabled(boolean) |
Set or get whether the components the action controls are enabled.
Invoking setEnabled(false) disables all the components that
the action controls. Similarly, invoking setEnabled(true) enables
the action's components. |
Method | Purpose |
---|---|
JMenuItem add(Action) (in JMenu and
JPopupMenu ) |
Create a JMenuItem object and put it in the menu or
popup menu. See the discussion in this section and in How
to Use Menus for details. |
JButton add(Action) (in JToolBar ) |
Create a JButton object and put it in the tool bar. See
the discussion in this section and in How
to Use Tool Bars for details. |
/* Uses actions with a tool bar and a menu. */ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JToolBar; import javax.swing.JButton; import javax.swing.ImageIcon; import javax.swing.JMenuItem; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JFrame; import javax.swing.JTextArea; import javax.swing.JScrollPane; import javax.swing.JPanel; import java.awt.*; import java.awt.event.*; public class ActionDemo extends JFrame { protected JTextArea textArea; protected String newline = "\n"; protected Action leftAction; protected Action middleAction; protected Action rightAction; public ActionDemo() { //Do frame stuff. super("ActionDemo"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create the toolbar and menu. JToolBar toolBar = new JToolBar(); JMenu mainMenu = new JMenu("Menu"); createActionComponents(toolBar, mainMenu); //Create the text area used for output. textArea = new JTextArea(5, 30); JScrollPane scrollPane = new JScrollPane(textArea); //Lay out the content pane. JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); contentPane.setPreferredSize(new Dimension(400, 150)); contentPane.add(toolBar, BorderLayout.SOUTH); contentPane.add(scrollPane, BorderLayout.CENTER); setContentPane(contentPane); //Set up the menu bar. JMenuBar mb = new JMenuBar(); mb.add(mainMenu); mb.add(createAbleMenu()); setJMenuBar(mb); } protected void createActionComponents(JToolBar toolBar, JMenu mainMenu) { JButton button = null; JMenuItem menuItem = null; //first button and menu item leftAction = new AbstractAction("Go left", new ImageIcon("left.gif")) { public void actionPerformed(ActionEvent e) { displayResult("Action for first button/menu item", e); } }; button = toolBar.add(leftAction); button.setText(""); //an icon-only button button.setToolTipText("This is the left button"); menuItem = mainMenu.add(leftAction); menuItem.setIcon(null); //arbitrarily chose not to use icon in menu //second button and menu item middleAction = new AbstractAction("Do something", new ImageIcon("middle.gif")) { public void actionPerformed(ActionEvent e) { displayResult("Action for second button/menu item", e); } }; button = toolBar.add(middleAction); button.setText(""); button.setToolTipText("This is the middle button"); menuItem = mainMenu.add(middleAction); menuItem.setIcon(null); //arbitrarily chose not to use icon in menu //third button and menu item rightAction = new AbstractAction("Go right", new ImageIcon("right.gif")) { public void actionPerformed(ActionEvent e) { displayResult("Action for third button/menu item", e); } }; button = toolBar.add(rightAction); button.setText(""); button.setToolTipText("This is the right button"); menuItem = mainMenu.add(rightAction); menuItem.setIcon(null); //arbitrarily chose not to use icon in menu } protected JMenu createAbleMenu() { JMenu ableMenu = new JMenu("Action State"); JCheckBoxMenuItem cbmi = null; cbmi = new JCheckBoxMenuItem("First action enabled"); cbmi.setSelected(true); cbmi.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JCheckBoxMenuItem mi = (JCheckBoxMenuItem)(e.getSource()); boolean selected = (e.getStateChange() == ItemEvent.SELECTED); leftAction.setEnabled(selected); } }); ableMenu.add(cbmi); cbmi = new JCheckBoxMenuItem("Second action enabled"); cbmi.setSelected(true); cbmi.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JCheckBoxMenuItem mi = (JCheckBoxMenuItem)(e.getSource()); boolean selected = (e.getStateChange() == ItemEvent.SELECTED); middleAction.setEnabled(selected); } }); ableMenu.add(cbmi); cbmi = new JCheckBoxMenuItem("Third action enabled"); cbmi.setSelected(true); cbmi.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JCheckBoxMenuItem mi = (JCheckBoxMenuItem)(e.getSource()); boolean selected = (e.getStateChange() == ItemEvent.SELECTED); rightAction.setEnabled(selected); } }); ableMenu.add(cbmi); return ableMenu; } protected void displayResult(String actionDescription, ActionEvent e) { String s = ("Action event detected by: " + actionDescription + newline + " Event source: " + e.getSource() + newline); textArea.append(s); } public static void main(String[] args) { ActionDemo frame = new ActionDemo(); frame.pack(); frame.setVisible(true); } }