An Action can be used to separate functionality and state from a component. For example, if you have two or more components that perform the same function, consider using an Action object to implement the function.package com.han;import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.net.URL;import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;@SuppressWarnings("serial")
public class ActionDemo extends JPanel implements ItemListener {
// Define some properties associated with buttons/"mainMenu".
private String[] names = { "Go left", "Do something", "Go right" };
private Integer[] mnemonics = { new Integer(KeyEvent.VK_L),
new Integer(KeyEvent.VK_M), new Integer(KeyEvent.VK_R) };
private String[] toolTipTexts = { "This is the left button",
"This is the middle button", "This is the right button" }; // Define the names for AbleMenu items.
private static String[] namesAbleMenu = { "First action enabled",
"Second action enabled", "Third action enabled" }; // Define properties related to image icons.
private String imageDir = "/images/jlfgr-1_0/toolbarButtonGraphics/navigation/";
private String[] icon24Names = { "Back24.gif", "Up24.gif", "Forward24.gif" };
private String[] icon24Captions = icon24Names;
private String[] icon16Names = { "Back16.gif", "Up16.gif", "Forward16.gif" };
private String[] icon16Captions = icon16Names; /**
 * There are three actions: leftAction, middleAction, rightAction.
 */
private static Action[] actions = new Action[3]; ActionDemo() {
super(new BorderLayout());// because by default JPanel uses FlowLayout. // Create a scrolled text area.
JTextArea textArea = new JTextArea();
textArea.setEditable(false);
textArea.setLineWrap(false);
textArea.setWrapStyleWord(false);
JScrollPane scrollPane = new JScrollPane(textArea); // Create the actions shared by the tool bar and menu.
for (int i = 0; i < names.length; i++) {
Icon icon24 = createImageIcon(imageDir + icon24Names[i],
icon24Captions[i]);
Icon icon16 = createImageIcon(imageDir + icon16Names[i],
icon16Captions[i]);
actions[i] = new SharedAction(names[i], icon24, icon16,
toolTipTexts[i], mnemonics[i], textArea);
} // Create a tool bar.
JToolBar toolBar = createToolBar(); // Lay out the content pane.
add(scrollPane, BorderLayout.CENTER);
add(toolBar, BorderLayout.NORTH);
setPreferredSize(new Dimension(450, 150));
} private JToolBar createToolBar() {
// TODO Auto-generated method stub
// JToolBar uses the BoxLayout by default.
JToolBar toolBar = new JToolBar("Navigation tool bar");
for (int i = 0; i < actions.length; i++) {
JButton button = new JButton(actions[i]);
toolBar.add(button);
}
return toolBar;
} private static JMenuBar createMenuBar() {
// TODO Auto-generated method stub
JMenuBar menuBar = new JMenuBar();
JMenu mainMenu = new JMenu("Menu");
JMenu ableMenu = new JMenu("Action state");
menuBar.add(mainMenu);
menuBar.add(ableMenu); // Declare and allocate memory address for "cbmis".
JCheckBoxMenuItem[] cbmis = new JCheckBoxMenuItem[3]; 

for (int i = 0; i < actions.length; i++) {
// add JMenuItem to "mainMenu".
mainMenu.add(new JMenuItem(actions[i]));

// Initialize "cbmis" and add them to "ableMenu".
cbmis[i] = new JCheckBoxMenuItem(new AbleMenuAction(
namesAbleMenu[i], cbmis, actions));
ableMenu.add(cbmis[i]);
}
return menuBar;
} /**
 * Return an Icon, or {@code null} if the path is invalid.
 * 
 * @param path
 *            - the image icon path
 * @param caption
 *            - the image description, which would allow assistive
 *            technologies to help visually impaired user understand what
 *            information the icon conveys.
 * @return an Icon object, or <code>null</code> if the given path is not
 *         valid.
 */
private Icon createImageIcon(String path, String caption) {
// TODO Auto-generated method stub
URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, caption);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
} @Override
public void itemStateChanged(ItemEvent e) {
// TODO Auto-generated method stub
// You can put the responses to the item selection action. However,
// since
// we have used the Action object for the JCheckBoxMenuItem, the items'
// selection state can be listened and processed in the Action.
} /**
 * Define actions for the mainMenu and toolBar buttons.
 * @author HAN
 * 
 */
private class SharedAction extends AbstractAction {
private JTextArea textArea;
private String newline = System.getProperty("line.separator"); SharedAction(String text, Icon buttonIcon, Icon menuIcon,
String toolTipText, Integer mnemonic, JTextArea textArea) {
this.textArea = textArea;

putValue(NAME, text);
putValue(LARGE_ICON_KEY, buttonIcon);
putValue(SMALL_ICON, menuIcon);
putValue(SHORT_DESCRIPTION, toolTipText);
putValue(MNEMONIC_KEY, mnemonic);
} // Methods inherited from interface must be overridden.
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
// Display some informations as we want to the text area.
textArea.append("Action event detected: ");
Object triggerComponent = e.getSource();
if (triggerComponent instanceof JButton) {
if (((JButton) triggerComponent).getText().equals(names[0])) {
textArea.append("Action for first button");
} else if (((JButton) triggerComponent).getText().equals(names[1])) {
textArea.append("Action for second button");
} else if (((JButton) triggerComponent).getText().equals(names[2])) {
textArea.append("Action for third button");
}
} else if (triggerComponent instanceof JMenuItem) {
if (((JMenuItem) triggerComponent).getText().equals(names[0])) {
textArea.append("Action for first mainMenu item");
} else if (((JButton) triggerComponent).getText().equals(names[1])) {
textArea.append("Action for second mainMenu item");
} else if (((JButton) triggerComponent).getText().equals(names[2])) {
textArea.append("Action for third mainMenu item");
}
}
textArea.append(newline);
textArea.setTabSize(4);
textArea.append("\t");
textArea.append("Event source: " + e.getSource());
textArea.append(newline);
} } /**
 * Create and show GUI. For thread safety, this method should be invoked
 * from the event-dispatching thread.
 */
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("Action demo apps");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Set up the content pane, where the "main GUI" lives.
frame.setContentPane(new ActionDemo()); // Set up the menu bar and add it to frame.
JMenuBar menuBar = createMenuBar();
frame.setJMenuBar(menuBar); // Show the window.
frame.pack();
frame.setVisible(true);
} public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
createAndShowGUI();
}
});
}
}/**
 * Define actions for the ableMenu.
 * 
 * @author HAN
 * 
 */
@SuppressWarnings("serial")
class AbleMenuAction extends AbstractAction {
private JCheckBoxMenuItem[] cbmis;
private Action[] actions; AbleMenuAction(String name, JCheckBoxMenuItem[] cbmis, Action[] actions) {
super(name);
this.cbmis = cbmis;
this.actions = actions; putValue(SELECTED_KEY, true);
} @Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JCheckBoxMenuItem cbmi = (JCheckBoxMenuItem) e.getSource();
boolean isSelected = cbmi.isSelected();
if (cbmi == cbmis[0]) {
actions[0].setEnabled(isSelected);
} else if (cbmi == cbmis[1]) {
actions[1].setEnabled(isSelected);
} else if (cbmi == cbmis[2]) {
actions[2].setEnabled(isSelected);
}
}}

解决方案 »

  1.   

    /**
     * An Action can be used to separate functionality and state from a component. 
     * For example, 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 action listener that provides not only action-event 
     * handling, but also centralized handling of the state of action-event-firing 
     * components such as tool bar buttons, menu items, common buttons, and text 
     * fields. The state that an action can handle includes text, icon, mnemonic, 
     * enabled, and selected status.
     * <p>
     * This relies on having the Java Look and Feel Graphics Repository
     * (jlfgr-1_0.jar) in the class path.
     * You can download this file from:
     * <pre>{@link http://www.oracle.com/technetwork/java/repository-140393.html}</pre>
     * Put it in the class path using one of the following commands<br>
     * (assuming jlfgr-1_0.jar is in a subdirectory named jars):<br>
     *
     *   java -cp .;jars/jlfgr-1_0.jar ActionDemo [Microsoft Windows]<br>
     *   java -cp .:jars/jlfgr-1_0.jar ActionDemo [UNIX]<br>
     * @author HAN
     *
     */