- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
13.19.9 菜单
菜单在 Swing 中做了重要的改进并且更加的灵活——例如,我们可以在几乎程序中任何地方使用他们,包括在面板和程序片中。语法同它们在老的 AWT 中是一样的,并且这样使出现在老 AWT 的在新的 Swing 也出现了:我们必须为我们的菜单艰难地编写代码,并且有一些不再作为资源支持菜单(其它事件中的一些将使它们更易转换成其它的编程语言)。另外,菜单代码相当的冗长,有时还有一些混乱。下面的方法是放置所有的关于每个菜单的信息到对象的二维数组里(这种方法可以放置我们想处理的任何事物到数组里),这种方法在解决这个问题方面领先了一步。这个二维数组被菜单所创建,因此它首先表示出菜单名,并在剩余的列中表示菜单项和它们的特性。我们会注意到数组列不必保持一致——只要我们的代码知道将发生的一切事件,每一列都可以完全不同。
//: Menus.java // A menu-building system; also demonstrates // icons in labels and menu items. package c13.swing; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Menus extends JPanel { static final Boolean bT = new Boolean(true), bF = new Boolean(false); // Dummy class to create type identifiers: static class MType { MType(int i) {} }; static final MType mi = new MType(1), // Normal menu item cb = new MType(2), // Checkbox menu item rb = new MType(3); // Radio button menu item JTextField t = new JTextField(10); JLabel l = new JLabel("Icon Selected", Faces.faces[0], JLabel.CENTER); ActionListener a1 = new ActionListener() { public void actionPerformed(ActionEvent e) { t.setText( ((JMenuItem)e.getSource()).getText()); } }; ActionListener a2 = new ActionListener() { public void actionPerformed(ActionEvent e) { JMenuItem mi = (JMenuItem)e.getSource(); l.setText(mi.getText()); l.setIcon(mi.getIcon()); } }; // Store menu data as "resources": public Object[][] fileMenu = { // Menu name and accelerator: { "File", new Character('F') }, // Name type accel listener enabled { "New", mi, new Character('N'), a1, bT }, { "Open", mi, new Character('O'), a1, bT }, { "Save", mi, new Character('S'), a1, bF }, { "Save As", mi, new Character('A'), a1, bF}, { null }, // Separator { "Exit", mi, new Character('x'), a1, bT }, }; public Object[][] editMenu = { // Menu name: { "Edit", new Character('E') }, // Name type accel listener enabled { "Cut", mi, new Character('t'), a1, bT }, { "Copy", mi, new Character('C'), a1, bT }, { "Paste", mi, new Character('P'), a1, bT }, { null }, // Separator { "Select All", mi,new Character('l'),a1,bT}, }; public Object[][] helpMenu = { // Menu name: { "Help", new Character('H') }, // Name type accel listener enabled { "Index", mi, new Character('I'), a1, bT }, { "Using help", mi,new Character('U'),a1,bT}, { null }, // Separator { "About", mi, new Character('t'), a1, bT }, }; public Object[][] optionMenu = { // Menu name: { "Options", new Character('O') }, // Name type accel listener enabled { "Option 1", cb, new Character('1'), a1,bT}, { "Option 2", cb, new Character('2'), a1,bT}, }; public Object[][] faceMenu = { // Menu name: { "Faces", new Character('a') }, // Optinal last element is icon { "Face 0", rb, new Character('0'), a2, bT, Faces.faces[0] }, { "Face 1", rb, new Character('1'), a2, bT, Faces.faces[1] }, { "Face 2", rb, new Character('2'), a2, bT, Faces.faces[2] }, { "Face 3", rb, new Character('3'), a2, bT, Faces.faces[3] }, { "Face 4", rb, new Character('4'), a2, bT, Faces.faces[4] }, }; public Object[] menuBar = { fileMenu, editMenu, faceMenu, optionMenu, helpMenu, }; static public JMenuBar createMenuBar(Object[] menuBarData) { JMenuBar menuBar = new JMenuBar(); for(int i = 0; i < menuBarData.length; i++) menuBar.add( createMenu((Object[][])menuBarData[i])); return menuBar; } static ButtonGroup bgroup; static public JMenu createMenu(Object[][] menuData) { JMenu menu = new JMenu(); menu.setText((String)menuData[0][0]); menu.setMnemonic( ((Character)menuData[0][1]).charValue()); // Create redundantly, in case there are // any radio buttons: bgroup = new ButtonGroup(); for(int i = 1; i < menuData.length; i++) { if(menuData[i][0] == null) menu.add(new JSeparator()); else menu.add(createMenuItem(menuData[i])); } return menu; } static public JMenuItem createMenuItem(Object[] data) { JMenuItem m = null; MType type = (MType)data[1]; if(type == mi) m = new JMenuItem(); else if(type == cb) m = new JCheckBoxMenuItem(); else if(type == rb) { m = new JRadioButtonMenuItem(); bgroup.add(m); } m.setText((String)data[0]); m.setMnemonic( ((Character)data[2]).charValue()); m.addActionListener( (ActionListener)data[3]); m.setEnabled( ((Boolean)data[4]).booleanValue()); if(data.length == 6) m.setIcon((Icon)data[5]); return m; } Menus() { setLayout(new BorderLayout()); add(createMenuBar(menuBar), BorderLayout.NORTH); JPanel p = new JPanel(); p.setLayout(new BorderLayout()); p.add(t, BorderLayout.NORTH); p.add(l, BorderLayout.CENTER); add(p, BorderLayout.CENTER); } public static void main(String args[]) { Show.inFrame(new Menus(), 300, 200); } } ///:~
这个程序的目的是允许程序设计者简单地创建表格来描述每个菜单,而不是输入代码行来建立菜单。每个菜单都产生一个菜单,表格中的第一列包含菜单名和键盘快捷键。其余的列包含每个菜单项的数据:字符串存在在菜单项中的位置,菜单的类型,它的快捷键,当菜单项被选中时被激活的动作接收器及菜单是否被激活等信息。如果列开始处是空的,它将被作为一个分隔符来处理。
为了预防浪费和冗长的多个 Boolean 创建的对象和类型标志,以下的这些在类开始时就作为 static final 被创建:bT 和 bF 描述 Booleans 和哑类 MType 的不同对象描述标准的菜单项(mi),复选框菜单项(cb),和单选钮菜单项(rb)。请记住一组 Object 可以拥有单一的 Object 句柄,并且不再是原来的值。
这个程序例子同样展示了 JLables 和 JMenuItems(和它们的衍生事物)如何处理图标的。一个图标经由它的构建器置放进 JLable 中并当对应的菜单项被选中时被改变。
菜单条数组控制处理所有在文件菜单清单中列出的,我们想显示在菜单条上的文件菜单。我们通过这个数组去使用 createMenuBar(),将数组分类成单独的菜单数据数组,再通过每个单独的数组去创建菜单。这种方法依次使用菜单数据的每一行并以该数据创建 JMenu,然后为菜单数据中剩下的每一行调用 createMenuItem() 方法。最后,createMenuItem() 方法分析菜单数据的每一行并且判断菜单类型和它的属性,再适当地创建菜单项。终于,像我们在菜单构建器中看到的一样,从表示 createMenuBar(menuBar) 的表格中创建菜单,而所有的事物都是采用递归方法处理的。
这个程序不能建立串联的菜单,但我们拥有足够的知识,如果我们需要的话,随时都能增加多级菜单进去。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论