6.1.4 JMenuItem类
JMenuItem组件是用户可以在菜单栏上选择的预定义组件。作为AbstractButton的子类,JMenuItem是一个特殊的按钮组件,其行为类似于JButton。除了作为AbstractButton的子类,JMenuItem类共享JButton的数据模型(ButtonModel接口与DefaultButtonModel实现)。
创建JMenuItem组件
JMenuItem有六个构造函数。这些构造函数可以使得我们初始化菜单项的字符串或是图标以及菜单项的热键。并不存在显式的构造函数允许我们在创建时设置所有三个选项,除非我们将其作为Action的一部分。
public JMenuItem()
JMenuItem jMenuItem = new JMenuItem();
public JMenuItem(Icon icon)
Icon atIcon = new ImageIcon("at.gif");
JMenuItem jMenuItem = new JMenuItem(atIcon);
public JMenuItem(String text)
JMenuItem jMenuItem = new JMenuItem("Cut");
public JMenuItem(String text, Icon icon)
Icon atIcon = new ImageIcon("at.gif");
JMenuItem jMenuItem = new JMenuItem("Options", atIcon);
public JMenuItem(String text, int mnemonic)
JMenuItem jMenuItem = new JMenuItem("Cut", KeyEvent.VK_T);
public JMenuItem(Action action)
Action action = ...;
JMenuItem jMenuItem = new JMenuItem(action);
热键可以使得我们通过键盘浏览选择菜单。例如,在Windows平台上,如果菜单项出现在已打开的Edit菜单中,我们可以通过简单的按下Alt-T来选中Cut菜单。菜单项的热键通常以菜单文本标签中的下划线形式出现。然而,如果字符并没有出现在文本标签中,或者是没有文本标签,用户通常并不会得到明显的提示。字符是通过java.awt.event.KeyEvent类中的不同常量来标识的。
其他的平台也许会提供其他的选中热键。在Unix平台下,通常是Alt键;而在Macintosh平台下则是Command键。
JMenuItem属性
JMenuItem有多个属性。大约有100个属性是通过各种超类来继承的。表6-3显示了JMenuItem特定的10个属性。
JMenuItem属性
属性名
|
数据类型
|
访问性
|
accelerator
|
KeyStroke
|
读写绑定
|
accessibleContext
|
AccessibleContext
|
只读
|
armed
|
boolean
|
读写
|
component
|
Component
|
只读
|
enabled
|
boolean
|
只写绑定
|
menuDragMouseListeners
|
MenuDragMouseListener[]
|
只读
|
menuKeyListeners
|
MenuKeyListener[]
|
只读
|
subElements
|
MenuElement[]
|
只读
|
UI
|
MenuElementUI
|
只写绑定
|
UIClassID
|
String
|
只读
|
其中比较有趣的一个属性就是accelerator。正如第2章所解释的,KeyStroke是一个工厂类,可以使得我们基于按键与标识符组合创建实例。例如,下面的代码语句来自于本章列表6-1中的示例,将Ctrl-X作为快捷键与一个特定的菜单项相关联:
KeyStroke ctrlXKeyStroke = KeyStroke.getKeyStroke("control X");
cutMenuItem.setAccelerator(ctrlXKeyStroke);
只读的component与subElement属性是JMenuItem所实现的MenuElement接口的一部分。component属性是菜单项的渲染器(JMenuItem本身)。subElement属性是空的(也就是一个空的数组,而不是null),因为JMenuItem并没有子类。
处理JMenuItem事件
我们可以在JMenuItem内部使用至少五种不同的方法来处理事件。组件继承了允许我们通过AbstractButton的ChangeListener与ActionListener注册的方法来触发ChangeEvent与ActionEvent的能力。中软皮,JMenuItem组件支持当MenuKeyEvent与MenuDragMouseEvent事件发生时注册MenuKeyListener与MenuDragMouseListener对象。这些技术会在后面的章节中进行讨论。第五种方法是向JMenuItem的构造函数传递Action,其作用类似于一种特殊的使用ActionListener监听的方法。要了解更多的关于使用Action的内容,可以查看本章稍后的“JMenu类”一节中关于在菜单中使用Action对象的讨论。
使用ChangeListener监听JMenuItem事件
通常我们并不会向JMenuItem注册ChangeListener。然而,演示一个理想的例子助于更为清晰的解释JMenuItem关于其ButtonModel数据模型的变化。所考虑的事件变化是与JButton相同的arm,press与select。然而,他们的名字会有一些迷惑,因为所选择的模型属性并没有进行设置。
当鼠标略过菜单选项并且菜单变为选中时,JMenuItem是armed。当用户释放其上的鼠标按钮时,JMenuItem是pressed。紧随按下之后,菜单项会变为未按下与unarmed。在菜单项变为按下与未按下之间,AbstractButton会得到模型变化的通知,从而使得菜单项所注册的ActionListener对象得到通知。一个普通JMenuItem的按钮模型不会报告被选中。如果我们没有选择而将鼠标移动到另一个菜单项上,则第一个菜单项会自动变化unarmed。为了有助于我们更好的理解不同的变化,图6-5显示了一个序列图。
使用ActionListener监听JMenuItem事件
关联到JMenuItem更好的监听器是ActionListener,或者是向构造函数传递一个Action。他可以使得我们确定哪一个菜单项被选中。当用户在作为打开菜单一部分的JMenuItem上释放鼠标按钮时,所注册的ActionListener对象会得到通知。如果用户通过键盘(箭头键或是热键)或是按下菜单快捷键来选中菜单时,所注册的监听器也会得到通知。
当我们希望菜单被选中时发生某个动作,我们必须为每一个JMenuItem添加一个ActionListener。并不存在一个自动的方法使得我们可以为JMenu或是JMenuBar注册一个ActionListener从而使得其所包含的JMenuItem对象通知一个ActionListener。
列表6-1中的示例程序为每一个JMenuItem关联了一个相同的ActionListener:
class MenuActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Selected: " + e.getActionCommand());
}
}
然而更为通常的是,我们为每一个菜单项关联一个不同的动作,从而每一个菜单项可以进行不同的响应。
提示:我们并不需要为组件创建一个自定义的ActionListener并进行注册,我们可以创建一个自定义的Action,并且在组件上调用setAction()方法。
使用MenuKeyListener监听JMenuItem事件
MenuKeyEvent是用户界面类内部为JMenu与JMenuItem所用的特殊的KeyEvent,使得组件可以监听何时其键盘热键被按下。要监听这种键盘输入,每一个菜单组件注册一个MenuKeyListener,从而监听相应的输入。如果键盘热键被按下,事件就会被处理,从而不会再被传送到所注册的监听器。如果键盘热键没有被按下,所注册的键盘监听器(而不是菜单键监听器)就会得到通知。
MenuKeyListener接口定义如下:
public interface MenuKeyListener extends EventListener {
public void menuKeyPressed(MenuKeyEvent e);
public void menuKeyReleased(MenuKeyEvent e);
public void menuKeyTyped(MenuKeyEvent e);
}
通常我们并不需要自己注册这种类型的监听器对象,尽管如果我们希望我们仍可以这样做。如果我们确定这样做,并且如果MenuKeyEvent发生(也就是一个键被按下/释放),JMenuBar中的每一个JMenu都会得到通知,就如同打开菜单中的每一个JMenuItem(或是子类)都有一个注册的MenuKeyListener。这包括禁止的菜单项,从而他们可以处理按下的热键。MenuKeyEvent类的定义如下:
public class MenuKeyEvent extends KeyEvent {
public MenuKeyEvent(Component source, int id, long when, int modifiers,
int keyCode, char keyChar, MenuElement path[], MenuSelectionManager mgr);
public MenuSelectionManager getMenuSelectionManager();
public MenuElement[] getPath();
}
确定当前选择路径是MenuSelectionManager的工作。选择路径是由顶层的JMenuBar上的JMenu到所选中的组件的菜单元素集合。对于大多数情况而言,管理器在幕后工作,而我们无需担心。
使用MenuDragMouseListener监听JMenuItem事件
与MenuKeyEvent类似,MenuDragMouseEvent也是用户界面类为JMenu与JMenuBar在内部所用的特殊的事件类型。正如其名字所显示的,MenuDragMouseEvent是一种特殊类型的MouseEvent。通过监听鼠标何时在打开的菜单中移动,用户界面类使用监听器来维护选择路径,从而确定当前选中的菜单项。其定义如下:
public interface MenuDragMouseListener extends EventListener {
public void menuDragMouseDragged(MenuDragMouseEvent e);
public void menuDragMouseEntered(MenuDragMouseEvent e);
public void menuDragMouseExited(MenuDragMouseEvent e);
public void menuDragMouseReleased(MenuDragMouseEvent e);
}
与MenuKeyListener类似,通常我们并不需要亲自监听这一事件。如果我们比较感兴趣一个菜单或是子菜单何时显示,要注册的更好的监听器是MenuListener,这个监听器可以注册到JMenu,但是并不可以注册到单个的JMenuItem。我们将会在描述JMenu的下一节了解到这一点。
MenuDragMouseEvent类的定义,MenuDragMouseListener方法的参数如下:
public class MenuDragMouseEvent extends MouseEvent {
public MenuDragMouseEvent(Component source, int id, long when, int modifiers,
int x, int y, int clickCount, boolean popupTrigger, MenuElement path[],
MenuSelectionManager mgr);
public MenuSelectionManager getMenuSelectionManager();
public MenuElement[] getPath();
}
自定义JMenuItem观感
与JMenuBar类似,预定义的观感类型提供了不同的JMenuItem外观以及默认的UIResource值集合。图6-3显示了预安装集合的JMenuItem的外观:Motif,Windows与Ocean。
表6-4显示了JMenuItem的UIResource相关属性集合。JMenuItem组件提供了20个不同的属性。
JMenuItem UIResource元素
|
属性字符串
|
对象类型
|
MenuItem.acceleratorDelimiter
|
String
|
MenuItem.acceleratorFont
|
Font
|
MenuItem.acceleratorForeground
|
Color
|
MenuItem.acceleratorSelectionForeground
|
Color
|
MenuItem.actionMap
|
ActionMap
|
MenuItem.arrowIcon
|
Icon
|
MenuItem.background
|
Color
|
MenuItem.border
|
Border
|
MenuItem.borderPainted
|
Boolean
|
MenuItem.checkIcon
|
Icon
|
MenuItem.commandSound
|
String
|
MenuItem.disabledForeground
|
Color
|
MenuItem.font
|
Font
|
MenuItem.foreground
|
Color
|
MenuItem.margin
|
Insets
|
MenuItem.opaque
|
Boolean
|
MenuItem.selectionBackground
|
Color
|
MenuItem.selectionForeground
|
Color
|
MenuItem.textIconGap
|
Integer
|
MenuItemUI
|
String
|
6.1.5 JMenu类
JMenu组件是放置在JMenuBar上的基本菜单项。当一个JMenu被选中时,菜单在JPopupMenu内显示所包含的菜单项。对于JMenuItem,JMenu的数据模型则是一个ButtonModel实现,或者更为特定的,DefaultButonModel。
创建JMenu组件
JMenu有四个构造函数可以使得我们初始化菜单的字符串标签:
public JMenu()
JMenu jMenu = new JMenu();
public JMenu(String label)
JMenu jMenu = new JMenu("File");
public JMenu(String label, boolean useTearOffs)
public JMenu(Action action)
Action action = ...;
JMenu jMenu = new JMenu(action);
其中一个构造函数用于tear-off菜单。然而,tear-off菜单当前并不被支持;所以其参数会被忽略。第四个构造函数使用Action中的属性来填充菜单。
注意:所谓tear-off菜单是显示在一个窗口中并且在选择之后仍然保持打开,而不是自动关闭。
向JMenu添加菜单项
一旦我们有了JMenu,我们需要向其添加JMenuItem对象;否则,菜单不会显示任何选择。有五个方法可以向JMenu添加所定义的菜单项,一个用于添加分隔符:
public JMenuItem add(JMenuItem menuItem);
public JMenuItem add(String label);
public Component add(Component component);
public Component add(Component component, int index);
public JMenuItem add(Action action);
public void addSeparator();
在本章前面的列表6-1中,所有的JMenuItem组件是通过第一个add()方法添加到JMenu组件的。为了简便起见,我们可以将JMenuItem的文本标签传递给JMenu的add()方法。这个方法会创建菜单项,设置其标签,并且传回新菜单项组件。然后我们可以将菜单项事件处理器绑定到这个新获得的菜单项。第三个add()方法表明我们可以在JMenu上放置任意的Component的,而不仅是JMenuItem。第四个add()方法允许我们按位置放置组件。最后一个add()方法变体,带有一个Action参数,将会在下一节进行讨论。
我们可以使用JMenu的addSeparator()方法添加分隔栏。例如,在列表6-1中,File菜单是使用类似下面的代码来创建的:
JMenu fileMenu = new JMenu("File");
JMenuItem newMenuItem = new JMenuItem("New");
fileMenu.add(newMenuItem);
JMenuItem openMenuItem = new JMenuItem("Open");
fileMenu.add(openMenuItem);
JMenuItem closeMenuItem = new JMenuItem("Close");
fileMenu.add(closeMenuItem);
fileMenu.addSeparator();
JMenuItem saveMenuItem = new JMenuItem("Save");
fileMenu.add(saveMenuItem);
fileMenu.addSeparator();
JMenuItem exitMenuItem = new JMenuItem("Exit");
fileMenu.add(exitMenuItem);
注意,addSpeparator()调用包围了添加Save菜单项的调用。
除了在菜单的结束处添加菜单项以外,我们可以将菜单项插入在指定的位置或是将分隔符插入在指定的位置,如下所示:
public JMenuItem insert(JMenuItem menuItem, int pos);
public JMenuItem insert(Action a, int pos);
public void insertSeparator(int pos);
当一个菜单被添加到JMenu后,他就被加入了内部的JPopupMenu。
菜单中使用Action对象
在第2章中描述了Aciton接口及其相关联的类。Action是ActionListener接口的扩展,并且包含用于自定义与其实现相关联的组件的一些特殊属性。
借助于AbstractAction这现,我们可以很容易的定义文本标签,图标,热键,工具提示文本,允许状态,以及一个与组件相分离的ActionListener。然后我们可以使用相关联的Action创建组件,并且不必为组件指定文本标签,图标,热键,工具提示文本,允许状态,或是ActionListener,因为这些属性来自Action。要了解详细的描述,可以参考第2章。
为了演示的需要,列表6-2创建了AbstractAction的一个特定实现,并且将其多次添加到JMenu中。一旦Action被添加到JMenu,选择JMenuItem将会借助JOptionPane类显示一个弹出对话框,我们会在第9章讨论这一主题 。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ShowAction extends AbstractAction {
Component parentComponent;
public ShowAction(Component parentComponent) {
super("About");
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_A));
this.parentComponent = parentComponent;
}
public void actionPerformed(ActionEvent actionEvent) {
Runnable runnable = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(
parentComponent, "About Swing",
"About Box V2.0", JOptionPane.INFORMATION_MESSAGE);
}
};
EventQueue.invokeLater(runnable);
}
}
下面的代码为列表6-1中的示例程序中的File与Edit菜单创建了一个ShowAction与一个JMenuItem。无需显示的设置菜单项属性,他会具有一个About文本标签与一个热键,并且会执行所定义的actionPerformed()方法作为其ActionListener。事实上,我们可以创建Action一次,然后可以将其关联到所需要的多个地方(或者是其他支持添加Action对象的组件)。
Action showAction = new ShowAction(aComponent);
JMenuItem fileAbout = new JMenuItem(showAction);
fileMenu.add(fileAbout);
JMenuItem editAbout = new JMenuItem(showAction);
editMenu.add(editAbout);
使用AbstractAction的副作用就是通过setEnabled(false)方法禁止Action时,相应的,会禁止所有由其创建的组件。
JMenu属性
除了由JMenu继承的100多个属性以外,表6-5显示了16个JMenu特定的属性。其中的一些属性覆盖了继承属性的行为。例如,accelerator属性的设置方法会在我们尝试为这个属性赋值时抛出错误。换句话说,快捷键并不为JMenu对象所支持。其余的属性描述了JMenu对象的当前状态及其所包含的菜单组件。
JMenu属性
|
属性名
|
数据类型
|
访问性
|
accelerator
|
KeyStroke
|
只写
|
accessibleContext
|
AccessibleContext
|
只读
|
component
|
Component
|
只读
|
delay
|
int
|
读写
|
itemCount
|
int |
只读
|
menuComponentCount
|
int
|
只读
|
menuComponents
|
Component[]
|
只读
|
menuListeners
|
MenuListener[]
|
只读
|
model
|
ButtonModel
|
只写绑定
|
popupMenu
|
JPopupMenu
|
只读
|
popupMenuVisible
|
boolean
|
读写
|
selected
|
boolean
|
读写
|
subElements
|
MenuElement[]
|
只读
|
tearOff
|
boolean
|
只读
|
topLevelMenu
|
boolean
|
只读
|
UIClassID
|
String
|
只读
|
delay属性表示在选择JMenu与发出JPopupMenu之间所逝去的时间。默认情况这个值为0,表示会立即显示子菜单。尝试将这个值设置负值会抛出IllegalArgumentException。
选择菜单组件
通常我们并不需要监听JMenu组件的选择。我们只需要监听单个的JMenuItem组件的选择。然而,与JMenuItem相比,我们会对JMenu所用的ChangeEvent的不同方法感兴趣。另外,当一个菜单被弹出或是关闭时,MenuEvent会通知我们。
使用ChangeListener监听JMenu事件
与JMenuItem类似,如果我们对于修改底层的ButtonModel比较感兴趣,我们可以向JMenu注册ChangeListener。奇怪的是,JMenu的ButtonModel的唯一的状态改变就是selected属性。当被选中时,JMenu显示其菜单项。当没有被选中时,弹出菜单会消失。
使用MenuListener监听JMenu事件
监听弹出菜单何时显示或是隐藏的更好的方法是就是向JMenu对象注册MenuListener对象。其定义如下:
public interface MenuListener extends EventListener {
public void menuCanceled(MenuEvent e);
public void menuDeselected(MenuEvent e);
public void menuSelected(MenuEvent e);
}
通过注册MenuListener,当JMenu在弹出菜单打开之前选中时,我们会得到通知。这可以使得我们自定义其菜单选项。除了得到相关联的弹出菜单何时被弹出的通知,当菜单被取消选中以及菜单被关闭时我们也会得到通知。正如下面的MenuEvent类定义所显示的,事件所提供的唯一信息就是源(菜单):
public class MenuEvent extends EventObject {
public MenuEvent(Object source);
}
提示:如果我们选择动态自定义JMenu上的项,在确保调用revalidate(),因为组件会在我们更新显示之前一直等待。
自定义JMenu观感
与JMenuBar和JMenuItem类似,预定义的观感提供了不同的JMenu外观以及默认的UIResource值集合。图6-3显示了预安装的观感类型集合的JMenu对象外观。
表6-6显示了JMenu的UIResource相关属性的集合。对于JMenu组件,有30个不同的属性。
JMenu UIResource元素
|
属性字符串
|
对象类型
|
menu
|
Color
|
Menu.acceleratorDelimiter
|
String
|
Menu.acceleratorFont
|
Font
|
Menu.acceleratorForeground
|
Color
|
Menu.acceleratorSelectionForeground
|
Color
|
Menu.ActionMap
|
ActionMap
|
Menu.arrowIcon
|
Icon
|
Menu.background
|
Color
|
Menu.border
|
Border
|
Menu.borderPainted
|
Boolean
|
Menu.checkIcon
|
Icon
|
Menu.delay
|
Integer
|
Menu.disabledForeground
|
Color
|
Menu.font
|
Font
|
Menu.foreground
|
Color
|
Menu.margin
|
Insets
|
Menu.menuPopupOffsetX
|
Integer
|
Menu.menuPopupOffsetY
|
Integer
|
Menu.opaque
|
Boolean
|
Menu.selectionBackground
|
Color
|
Menu.selectionForeground
|
Color
|
Menu.shortcutKeys
|
int[]
|
Menu.submenuPopupOffsetX
|
Integer
|
Menu.submenuPopupOffsetY
|
Integer
|
Menu.textIconGap
|
Integer
|
Menu.useMenuBarBackgroundForTopLevel
|
Boolean
|
menuPressedItemB
|
Color
|
menuPressedItemF
|
Color
|
menuText
|
Color
|
MenuUI
|
String
|
分享到:
相关推荐
博文链接:https://clarancepeng.iteye.com/blog/197429
该记事本主要功能:主...格式菜单:包括自动换行、字体、颜色三个菜单项,主要实现了文档内容自动换行,调用Swing组件自带的颜色对话框,以及调用新创建的字体对话框;弹出式菜单:实现对文档的复制、剪切、粘贴功能。
工具栏:JToolBar 桌面窗格:JDesktopPane 内部框架:JInternalFrame 分层窗格:JLayeredPane 标签:JLabel 按钮:JButton 开启/关闭按钮:JToggleButton 复选框:JCheckBox 单选按钮:JRadioButton 按钮组:...
工具栏和菜单是几乎所有的GUI程序都需要设计的界面元素,它们为应用程序提供了快速执行特定方法和程序逻辑的用户接口。...本章介绍工具栏和菜单的设计,伸缩面板、数值组件、浏览器和系统托盘等控件的设计与使用。
利用Java Swing提供的各种组件开发出一款具有一定实用功能的文本编辑器。该编辑器能完成的主要功能:菜单栏、工具栏、快显菜单以及文件、编辑、视图等菜单内的常用子项目。学习和掌握Java Swing的相关知识
简易文本编辑器111111111111111111111111
com_ssepan_mvcform:Java Swing GUI应用程序,带有一些标准菜单项,工具栏项和状态栏。 使用动作事件来实现它们(进行中的工作)(连接属性已更改并控制已更改的事件)
Swing还提供了许多其他的GUI组件和功能,如文本框、标签、列表、菜单、工具栏、进度条、表格等。开发人员可以使用这些组件和功能来构建复杂的GUI应用程序。此外,Swing还提供了许多皮肤和主题,可以用于美化应用程序...
随着计算机与软件的进步,人机交互...如编辑框,滚动条,弹出菜单等的做法,由此形成了一个开发swing风格界面的 集成界面模板工具。最后,文章结尾总结了提出和研究设计的这套方案在意义和不足,以及进一步的工作。
纯Java编写的记事本 包含源码 实现了许多功能例如:定时保存、日历、字数统计,工具栏等一些功能。特别适合初学swing的人员阅读。
主窗体工具栏设计 8、图书信息管理模块 图书信息添加界面设计 检测书籍编号是否已存在 保存图书信息 图书信息修改界面设计 在图书修改表单中显示图书信息 修改图书信息 9、开发技巧和难点分析 多窗体...
要工具栏还是不要工具栏? 125 设置字体 126 使用展示窗口 127 <object> 标签 128 四种 activator 129 添加内容敏感的帮助 130 窗口级帮助 131 字段级帮助 131 屏幕级帮助 133 添加嵌入帮助 135 添加搜索功能 136 ...
一步一步地实现菜单栏(JMenuBar)工具栏(JPopupMenu)组合框(JComboBox)复选框(JCheckBox)单选按钮(JRadioButton)文本域的综合应用(三) 源程序
对话框,及自定义对话框- 菜单和工具栏- 自定义绘图- JList 列表框的用法,以及单元格的自定义显示- JTable 表格的用法,以及单元格的自定义显示- 一个基于 JTable 和 JSON 的学生管理系统- Java Swing应用程序的...
主要包括如何学好编程、Java语言概述、主流开发工具、Java语言基础、流程控制、Java数组、字符串、面向对象编程基础、继承、封装和多态、抽象类与接口、Java的类中类、包装类、数字类、集合类、格式类、输入输出、...
杰笛动作框架就提供一个比Swing自带的更好的工具栏和菜单栏。它提供了一个叫命令栏(CommandBar)的组件,可以取代Swing自带的JToolBar和JMenuBar。 杰笛动作框架有各种各样的风格。在当前的版本里,我们提供了...
若我们能将一般常用的功能以工具栏方式呈现在菜单下,让用户很快得到他想要 的功能,不仅增加用户使用软件的意愿,也加速工作的运行效率.这就是使用 ToolBar 的好处。 (2)用户可以拖拽出一个独立的可显示工具控件的...
只能输入0~255数字的IP地址 JListChooser 列表选择对话框 JNumberField 数字输入框,可限制小数位数,数字最大长度,最大最小能输入的数字 JPopupButton 带下拉菜单的工具栏按钮 JStatusBar 模拟Windows的...