1. 菜单栏、菜单、菜单项之间的关系:
1) 菜单栏(MenuBar)就是窗口中常见的顶层菜单栏,包含文件、编辑、格式等等子菜单的菜单条,即包含菜单的容器;
2) 菜单(Menu)是必定包含菜单项或者菜单(嵌套包含菜单,也叫子菜单)的容器;
3) 菜单项(MenuItem)即最小单位,即可以单击产生特效的菜单按钮,存在于菜单中的元素;
!!注意:Menu是MenuItem的子类,因此Menu是一种特殊的菜单项,可以作为Menu自己中的元素,作为二级菜单出现;
!!在AWT中Menu在MenuBar中是正常的(只有文本标签显示出来),而Menu在Menu中则必定是二级子菜单,除了显示文本标签之外,必定显示一个右角标,表示这是一个二级菜单,可以再展开一摞菜单项;
2. 如何制作菜单:
1) 首先需要一个菜单栏,使用MenuBar的构造器:MenuBar(); // 只有一个默认的无参构造器
!!将菜单栏和窗口绑定在一起使用Frame的setMenuBar方法:public void Frame.setMenuBar(MenuBar mb); // 指定菜单栏参数
2) 接着需要在菜单栏中添加菜单(一级子菜单):
i. 创建子菜单,使用Menu的构造器:Menu(String label); // 指定菜单的文本标签
ii. 将子菜单加入到菜单栏中,使用MenuBar的add方法(就跟普通容器一样添加):Menu MenuBar.add(Menu m); // 返回的是加入的子菜单
3) 为子菜单添加菜单项:
i. 首先要创建菜单项,使用MenuItem的构造器:MenuItem(String label); // 菜单项的文本标签
ii. 有时需要为菜单项指定快捷键,那么就需要使用可以指定快捷键的构造器:MenuItem(String label, MenuShortcut s); // MenuShortcut是菜单项快捷键类
a. MenuShortcut构造器:MenuShortcut(int key); // 默认Ctrl+key的组合作为快捷键
b. 加Shift组合:MenuShortcut(int key, boolean useShiftModifier); // 第二个参数如果为true表示使用Ctrl+Shift+key的组合作为快捷键;
!!注意快捷键和加速键的区别:快捷键必须要使用Ctrl(Shift可选),而加速键必须要使用Alt;
!!key是KeyEvent类定义的静态常量,全部用虚拟键表示,比如'X'就是KeyEvent.VK_X,'/'就是KeyEvent.VK_SLASH,具体是什么可以翻阅手册;
iii. 使用Menu的add方法将菜单项或者下级子菜单加入其中:MenuItem Menu.add(MenuItem mi); // 返回的是加入的菜单项
!!由于Menu是MenuItem的子类,因此还是使用该方法添加下级子菜单;
!!如果加的是子菜单那么会显示出一个右角标!!表示这是一个下级子菜单,可以进一步展开;
iv. 示例:Menu m = new Menu("File"); m.add(new MenuItem("Copy", new MenuShortcut(KeyEvent.VK_C)); // 创建了一个Ctrl+C的快捷键菜单项“复制”
!!添加下级子菜单和其菜单项的步骤重复3)即可,仅仅就是简单的嵌套;
3. 菜单分隔符以及添加菜单项的更简单的方法:
1) 有时候需要将子菜单中的各个菜单项按照逻辑分类,此时可以用分隔符将类型相同的菜单项分到一组去;
2) 有三种方法可以做到:
i. void Menu.addSeparator();
ii. void Menu.add(String label); // 该方法可以直接添加菜单项,根据文本标签添加菜单项,其实现
public void add(String label) {
add(new MenuItem(label));
}
!!可以看到这是对add方法的重载;
!!这种方法直接add("-");就添加了一条分隔符
iii. void Menu.add(MenuItem mi); // 直接add(new MenuItem("-");就可以添加分隔符
3) 一般推荐方法ii.,最为简洁;
4. 菜单事件处理:
1) 至于单击菜单弹出子菜单等工作都由AWT自动完成,无需程序员管理;
2) 用户需要自己处理的只有菜单项单击事件,该事件属于ActionEvent类型;
3) 但是ActionListener接口只有actionPerformed一个方法,因此要监控所有菜单项的单击事件就必须在该方法中加以判断;
4) 判断是那个菜单项的单击事件还是很简单的,只需要调用e.getActionCommand方法就能获取发生事件的菜单项上的标签文本了,示例:
ActionListener menuListener = e -> {
String cmd = e.getActionCommand();
ta.append("Click '" + cmd + "' menu item.\n");
if (cmd.equals("Exit")) {
System.exit(0);
}
};
5) 最后只要将监听器注册给菜单项即可:public synchronized void MenuItem.addActionListener(ActionListener l);
5. 复选菜单项:
1) CheckboxMenuItem,即最左侧带一个复选勾菜单项,单击一次打钩并关闭菜单,再单击一次取消打钩并关闭菜单;
2) 构造器:CheckboxMenuItem(String label); // 就只有指定标签文本的版本
3) 添加这种菜单项的操作和普通的MenuItem一模一样,ChecboxMenuItem是MenuItem的子类;
!!注意:复选菜单项不产生ActionEvent事件,因此不能用ActionListener来监控它;
6. 示例:
public class AwtTest {
public void init() {
Frame f = new Frame("Menu Test");
MenuBar mb = new MenuBar(); f.setMenuBar(mb);
Menu file = new Menu("File"); mb.add(file);
MenuItem newItem = new MenuItem("New"); file.add(newItem);
MenuItem saveItem = new MenuItem("Save"); file.add(saveItem);
MenuItem exitItem = new MenuItem("Exit", new MenuShortcut(KeyEvent.VK_X)); file.add(exitItem);
Menu edit = new Menu("Edit"); mb.add(edit);
CheckboxMenuItem autoWrap = new CheckboxMenuItem("Auto wrap"); edit.add(autoWrap);
edit.addSeparator();
MenuItem copyItem = new MenuItem("Copy"); edit.add(copyItem);
MenuItem pasteItem = new MenuItem("Paste"); edit.add(pasteItem);
edit.add(new MenuItem("-"));
Menu format = new Menu("Format"); edit.add(format);
MenuItem commentItem = new MenuItem("Comment", new MenuShortcut(KeyEvent.VK_SLASH, true));
format.add(commentItem);
MenuItem cancelItem = new MenuItem("Cancel comment"); format.add(cancelItem);
TextArea ta = new TextArea(6, 40); f.add(ta);
ActionListener menuListener = e -> {
String cmd = e.getActionCommand();
ta.append("Click '" + cmd + "' menu item.\n");
if (cmd.equals("Exit")) {
System.exit(0);
}
};
newItem.addActionListener(menuListener);
saveItem.addActionListener(menuListener);
exitItem.addActionListener(menuListener);
// autoWrap.addActionListener(menuListener); // CheckboxMenuItem不触发ActionEvent!!
copyItem.addActionListener(menuListener);
pasteItem.addActionListener(menuListener);
commentItem.addActionListener(menuListener);
cancelItem.addActionListener(menuListener);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
// super.windowClosing(e);
System.exit(0);
}
});
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new AwtTest().init();
}
}