控制台程序。
动作Action是任何实现了javax.swing.Action接口的类的对象。这个接口声明了操作Action对象的方法,例如,存储与动作相关的属性、启用和禁用动作。Action接口扩展了ActionListener接口,所以Action对象既是监听器,也是动作。
一些Swing组件,包括JMenu和JToolBar类型的组件,都有add()方法,可以接受Action类型的参数。当使用add()方法把Action对象添加到JMenu对象中,add()方法就会创建类型自动正确的组件。如果把Action对象添加到JMenu对象中,add()方法就会创建并返回JmentItem对象。另一方面,当把相同的Action对象添加到Action对象中时,会创建并返回JButton类型的对象。这意味着可以给菜单和工具栏添加相同的Action对象,因为Action对象是自己的监听器,所以可以自动获得由相同动作支持的菜单项和工具栏按钮。
下面使用Action重建SketcherFrame类:
1 // Frame for the Sketcher application 2 import javax.swing.*; 3 import java.awt.event.*; 4 import java.awt.*; 5 6 import static java.awt.event.InputEvent.*; 7 import static java.awt.AWTEvent.*; 8 import static java.awt.Color.*; 9 import static Constants.SketcherConstants.*; 10 11 @SuppressWarnings("serial") 12 public class SketcherFrame extends JFrame { 13 // Constructor 14 public SketcherFrame(String title) { 15 setTitle(title); // Set the window title 16 setJMenuBar(menuBar); // Add the menu bar to the window 17 setDefaultCloseOperation(EXIT_ON_CLOSE); // Default is exit the application 18 19 createFileMenu(); // Create the File menu 20 createElementMenu(); // Create the element menu 21 createColorMenu(); // Create the element menu 22 } 23 24 // Create File menu item actions 25 private void createFileMenuActions() { 26 newAction = new FileAction("New", 'N', CTRL_DOWN_MASK); 27 openAction = new FileAction("Open", 'O', CTRL_DOWN_MASK); 28 closeAction = new FileAction("Close"); 29 saveAction = new FileAction("Save", 'S', CTRL_DOWN_MASK); 30 saveAsAction = new FileAction("Save As..."); 31 printAction = new FileAction("Print", 'P', CTRL_DOWN_MASK); 32 exitAction = new FileAction("Exit", 'X', CTRL_DOWN_MASK); 33 34 // Initialize the array 35 FileAction[] actions = {openAction, closeAction, saveAction, saveAsAction, printAction, exitAction}; 36 fileActions = actions; 37 } 38 39 // Create the File menu 40 private void createFileMenu() { 41 JMenu fileMenu = new JMenu("File"); // Create File menu 42 fileMenu.setMnemonic('F'); // Create shortcut 43 createFileMenuActions(); // Create Actions for File menu item 44 45 // Construct the file drop-down menu 46 fileMenu.add(newAction); // New Sketch menu item 47 fileMenu.add(openAction); // Open sketch menu item 48 fileMenu.add(closeAction); // Close sketch menu item 49 fileMenu.addSeparator(); // Add separator 50 fileMenu.add(saveAction); // Save sketch to file 51 fileMenu.add(saveAsAction); // Save As menu item 52 fileMenu.addSeparator(); // Add separator 53 fileMenu.add(printAction); // Print sketch menu item 54 fileMenu.addSeparator(); // Add separator 55 fileMenu.add(exitAction); // Print sketch menu item 56 menuBar.add(fileMenu); // Add the file menu 57 } 58 59 // Create Element menu actions 60 private void createElementTypeActions() { 61 lineAction = new TypeAction("Line", LINE, 'L', CTRL_DOWN_MASK); 62 rectangleAction = new TypeAction("Rectangle", RECTANGLE, 'R', CTRL_DOWN_MASK); 63 circleAction = new TypeAction("Circle", CIRCLE,'C', CTRL_DOWN_MASK); 64 curveAction = new TypeAction("Curve", CURVE,'U', CTRL_DOWN_MASK); 65 66 // Initialize the array 67 TypeAction[] actions = {lineAction, rectangleAction, circleAction, curveAction}; 68 typeActions = actions; 69 } 70 71 // Create the Element menu 72 private void createElementMenu() { 73 createElementTypeActions(); 74 elementMenu = new JMenu("Elements"); // Create Elements menu 75 elementMenu.setMnemonic('E'); // Create shortcut 76 createRadioButtonDropDown(elementMenu, typeActions, lineAction); 77 menuBar.add(elementMenu); // Add the element menu 78 } 79 80 // Create Element menu actions 81 private void createElementColorActions() { 82 redAction = new ColorAction("Red", RED, 'R', CTRL_DOWN_MASK|ALT_DOWN_MASK); 83 yellowAction = new ColorAction("Yellow", YELLOW, 'Y', CTRL_DOWN_MASK|ALT_DOWN_MASK); 84 greenAction = new ColorAction("Green", GREEN, 'G', CTRL_DOWN_MASK|ALT_DOWN_MASK); 85 blueAction = new ColorAction("Blue", BLUE, 'B', CTRL_DOWN_MASK|ALT_DOWN_MASK); 86 87 // Initialize the array 88 ColorAction[] actions = {redAction, greenAction, blueAction, yellowAction}; 89 colorActions = actions; 90 } 91 92 // Create the Color menu 93 private void createColorMenu() { 94 createElementColorActions(); 95 colorMenu = new JMenu("Color"); // Create Elements menu 96 colorMenu.setMnemonic('C'); // Create shortcut 97 createRadioButtonDropDown(colorMenu, colorActions, blueAction); 98 menuBar.add(colorMenu); // Add the color menu 99 } 100 101 // Menu creation helper 102 private void createRadioButtonDropDown(JMenu menu, Action[] actions, Action selected) { 103 ButtonGroup group = new ButtonGroup(); 104 JRadioButtonMenuItem item = null; 105 for(Action action : actions) { 106 group.add(menu.add(item = new JRadioButtonMenuItem(action))); 107 if(action == selected) { 108 item.setSelected(true); // This is default selected 109 } 110 } 111 } 112 113 // Inner class defining Action objects for File menu items 114 class FileAction extends AbstractAction { 115 // Create action with a name 116 FileAction(String name) { 117 super(name); 118 } 119 120 // Create action with a name and accelerator 121 FileAction(String name, char ch, int modifiers) { 122 super(name); 123 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 124 125 // Now find the character to underline 126 int index = name.toUpperCase().indexOf(ch); 127 if(index != -1) { 128 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 129 } 130 } 131 132 // Event handler 133 public void actionPerformed(ActionEvent e) { 134 // You will add action code here eventually... 135 } 136 } 137 138 // Inner class defining Action objects for Element type menu items 139 class TypeAction extends AbstractAction { 140 // Create action with just a name property 141 TypeAction(String name, int typeID) { 142 super(name); 143 this.typeID = typeID; 144 } 145 146 // Create action with a name and an accelerator 147 private TypeAction(String name,int typeID, char ch, int modifiers) { 148 this(name, typeID); 149 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 150 151 // Now find the character to underline 152 int index = name.toUpperCase().indexOf(ch); 153 if(index != -1) { 154 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 155 } 156 } 157 158 public void actionPerformed(ActionEvent e) { 159 elementType = typeID; 160 } 161 162 private int typeID; 163 } 164 165 // Handles color menu items 166 class ColorAction extends AbstractAction { 167 // Create an action with a name and a color 168 public ColorAction(String name, Color color) { 169 super(name); 170 this.color = color; 171 } 172 173 // Create an action with a name, a color, and an accelerator 174 public ColorAction(String name, Color color, char ch, int modifiers) { 175 this(name, color); 176 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 177 178 // Now find the character to underline 179 int index = name.toUpperCase().indexOf(ch); 180 if(index != -1) { 181 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 182 } 183 } 184 185 public void actionPerformed(ActionEvent e) { 186 elementColor = color; 187 188 // This is temporary just to show it works... 189 getContentPane().setBackground(color); 190 } 191 192 private Color color; 193 } 194 195 // File actions 196 private FileAction newAction, openAction, closeAction, saveAction, saveAsAction, printAction, exitAction; 197 private FileAction[] fileActions; // File actions as an array 198 199 // Element type actions 200 private TypeAction lineAction, rectangleAction, circleAction, curveAction; 201 private TypeAction[] typeActions; // Type actions as an array 202 203 // Element color actions 204 private ColorAction redAction, yellowAction,greenAction, blueAction; 205 private ColorAction[] colorActions; // Color actions as an array 206 207 private JMenuBar menuBar = new JMenuBar(); // Window menu bar 208 private JMenu elementMenu; // Elements menu 209 private JMenu colorMenu; // Color menu 210 private Color elementColor = DEFAULT_ELEMENT_COLOR; // Current element color 211 private int elementType = DEFAULT_ELEMENT_TYPE; // Current element type 212 }
需要3个内部类来定义动作:一个用于File菜单项;第二个用于元素类型菜单项;第三个用于元素颜色菜单项。这些类都派生于实现了Aciton接口的javax.swing.AbstractAction类。AbstractAction类有3个构造函数,无参构造函数会创建带有默认名称和图标的对象;可以仅仅提供String类型的名称参数,此时会获得默认图标;最后,还可以提供名称和Icon类型的图标作为参数。
其它部分和以前一样:
1 // Sketching application 2 import javax.swing.*; 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class Sketcher { 7 public static void main(String[] args) { 8 theApp = new Sketcher(); // Create the application object 9 SwingUtilities.invokeLater(new Runnable() { 10 public void run() { 11 theApp.createGUI(); // Call GUI creator 12 } 13 }); 14 } 15 16 // Method to create the application GUI 17 private void createGUI() { 18 window = new SketcherFrame("Sketcher"); // Create the app window 19 Toolkit theKit = window.getToolkit(); // Get the window toolkit 20 Dimension wndSize = theKit.getScreenSize(); // Get screen size 21 22 // Set the position to screen center & size to half screen size 23 window.setSize(wndSize.width/2, wndSize.height/2); // Set window size 24 window.setLocationRelativeTo(null); // Center window 25 26 window.addWindowListener(new WindowHandler()); // Add window listener 27 window.setVisible(true); 28 } 29 30 // Handler class for window events 31 class WindowHandler extends WindowAdapter { 32 @Override 33 // Handler for window closing event 34 public void windowClosing(WindowEvent e) { 35 // Code to be added here... 36 } 37 } 38 39 private SketcherFrame window; // The application window 40 private static Sketcher theApp; // The application object 41 }
导入自定义包文件:
1 // Defines application wide constants 2 package Constants; 3 import java.awt.Color; 4 5 public class SketcherConstants { 6 // Element type definitions 7 public final static int LINE = 101; 8 public final static int RECTANGLE = 102; 9 public final static int CIRCLE = 103; 10 public final static int CURVE = 104; 11 12 // Initial conditions 13 public final static int DEFAULT_ELEMENT_TYPE = LINE; 14 public final static Color DEFAULT_ELEMENT_COLOR = Color.BLUE; 15 }