swing事件处理机制,swing事件处理的过程中涉及哪些对象
2.3特定于Swing的事件处理
记住,Swing组件是建立在AWT库之上的,Swing组件库有一些改进的功能,使得事件处理更加容易。功能改进涵盖了AWT的核心事件处理特性,从基本的动作监控到焦点管理。
为了简化事件处理,Swing library用Action interface扩展了原来的ActionListener接口,用事件处理程序存储可视属性。这使得事件处理程序的创建独立于可视化组件。然后,当该动作后来与一个组件相关联时,该组件被事件处理程序直接自动获取(例如,按钮标签)。这包括当动作被修改时更新标签的通知。AbstractAction和TextAction类实现了这个概念。
Swing库还增加了击键类,方便我们响应键盘事件。当一个特定的击键序列被按下时,我们可以通知组件它必须响应一个特定的动作,而不用监视一个特定键的所有击键事件。这些击键到动作的映射存储在InputMap和ActionMap对象的组合中。当组件容器有信息时,InputMap将实例化ComponentInputMap。在Keymap接口的帮助下,Swing text component可以使用这些来更容易地存储击键到动作的映射。第16章更详细地描述了TextAction支持的映射,以及其余的文本事件处理功能。
KeyboardFocusManager和DefaultKeyboardFocusManager在FocusTraversalPolicy及其实现的帮助下,管理焦点子系统。InputVerifier用于用户输入验证。这些内容将在本章后面的Swing组件管理中讨论。
2.3.1动作界面
Action接口是ActionListener接口的扩展,可以灵活地用于定义独立于作为触发器代理的组件的共享事件处理程序。该接口实现ActionListener,并定义一个以键值作为属性的查询表数据结构。然后,当一个动作与一个组件相关联时,这些显示属性会自动转移到该动作。以下是接口定义:
公共接口操作实现ActionListener {
//常数
public final静态字符串ACCELERATOR _ KEY
public final静态字符串ACTION _ COMMAND _ KEY
公共最终静态字符串默认值;
public final静态字符串LONG _ DESCRIPTION
public final静态字符串助记符_ KEY
公共最终静态字符串名称;
public final静态字符串SHORT _ DESCRIPTION
public final静态字符串SMALL _ ICON//侦听器
public void addpropertychangelister(propertychangelister listener);
public void removepropertychangelister(propertychangelister listener);
//属性
公共布尔值is enabled();
public void setEnabled(布尔new value);
//其他方法
公共对象getValue(字符串键);
public void putValue(字符串键,对象值);
}
因为Action只是一个接口,所以Swing提供了一个类来实现这个接口,这个类就是AbstractAction。
抽象操作类
AbstractAction类提供了Action接口的默认实现。这是实现属性行为的地方。
使用动作
一旦我们通过继承定义了一个AbstractAction并提供了一个公共的void action performed(ActionEvent ActionEvent)方法,我们就可以把它传递给一些特殊的Swing组件。JCheckBox、JToggleButton、JMenuItem、JCheckBoxMenuItem和JRadioButtonMenuItem提供了通过动作创建组件的构造函数,而Swing文本组件通过Keymap、InputMap和ActionMap提供了对动作对象的内置支持。
当具有关联动作的组件被添加到相应的Swing容器时,选择Action performed(ActionEvent ActionEvent)方法将触发对该动作的调用。组件的显示由添加到内部数据结构的属性元素定义。出于演示的目的,清单2-8提供了一个带有打印标签和图标的动作。当它被激活时,它会输出一个Hello,World消息。
导入Java . awt . event . *;
导入javax . swing . *;
公共类PrintHelloAction扩展AbstractAction {
私有静态最终图标print Icon=new image Icon( print . gif );
PrintHelloAction() {
super(Print ,Print icon);
putValue(动作简短描述你好,世界);
已执行公共void操作(ActionEvent ActionEvent){
System.out.println(Hello,World );
}
在我们将行动与对象相关联之后,如果我们发现我们需要修改行动的属性,我们只需要在一个地方修改其设置。因为所有的属性都是绑定的,他们会传播到使用行动的任意组件。例如,禁止动作(打印动作。set enabled(false))将会禁止分别在菜单与工具条上所创建的菜单与JButton。相应的,通过printAction.putValue(操作。名称,"你好,世界")修改行动的名字将会修改相关联组件的文本标签。
图2-6j工具栏与菜单上的打印你好行动的样子。可选中的按钮用来允许或是禁止行动,同时也可以修改其名字。
此示例的完整代码显示在列表2-9中。不要担心工具栏与菜单栏的创建。我们将会在第6章对其进行详细的讨论。
/**
包swingstudy.ch02
导入Java。awt。borderlayout
导入Java。awt。事件队列;
导入Java。awt。事件。动作事件;
导入Java。awt。事件。动作监听器;
导入javax。挥棒。行动;
导入javax。挥棒。jbutton
导入javax。挥棒。jframe
导入javax。挥棒。jmenu
导入javax。挥棒。jmenubar
导入javax。挥棒。jmenuitem
导入javax。挥棒。jpanel
导入javax。挥棒。jtoolbar
* @作者联想
公共集体诉讼测试员{
* @param args
公共静态void main(String[] args) {
//TODO自动生成的方法存根
Runnable runner=new Runnable() {
公共无效运行(){
JFrame frame=新JFrame(动作示例);
框架。setdefaultcloseoperation(JFrame .EXIT _ ON _ CLOSE);
最终动作print Action=new prin hello Action();
JMenuBar menuBar=new JMenuBar();
JMenu menu=new JMenu( File );
menuBar.add(菜单);
菜单。add(新的JMenuItem(打印操作));
JToolBar toolBar=new JToolBar();
工具栏. add(新的JButton(打印动作));
JButton Enable button=new JButton( Enable );
操作侦听器enableActionListener=新操作侦听器(){
已执行公共无效操作(操作事件事件){
打印操作。set enabled(真);
启用按钮。addactionlistener(enableActionListener);
JButton Disable button=new JButton( Disable );
操作侦听器disableActionListener=新操作侦听器(){
已执行公共无效操作(操作事件事件){
打印操作。set enabled(假);
禁用按钮。addactionlistener(disableActionListener);
JButton Relabel button=new JButton( Relabel );
操作侦听器relabelActionListener=新操作侦听器(){
已执行公共无效操作(操作事件事件){
printAction.putValue(操作。名,你好,世界);
重新标记按钮。addactionlistener(relabelActionListener);
JPanel按钮面板=new JPanel();
按钮面板。添加(启用按钮);
按钮面板。添加(禁用按钮);
按钮面板。添加(重新标记按钮);
frame.setJMenuBar(菜单栏);
frame.add(工具栏,BorderLayout .南);
frame.add(buttonPanel,BorderLayout .北);
frame.setSize(300,200);
框架。设置可见(真);
事件队列。稍后调用(runner);
}
其余的绑定属性通过putValue(字符串键,对象值)放置在查询表中。获取当前的键属性设置可以使得我们查看可以进行哪些设置,而不需要进行单独请求。表2-3描述了可以用作键值的行动预定义常量集合。我们也可以添加我们自己的常量,从而在以后动作发生时进行查询。
一旦一个属性已经存放在查询表中,我们可以通过公共对象getValue(字符串键)进行获取。其作用方式类似于java.util.Hashtable类或是java.util.Map接口,区别在于:如果表中存在一个键值,那么我们尝试存入一个具有空值的键/值对,则查询表会移除这个键值。
击键类
特定JComponent的击键类和inputMap和actionMap属性提供了一种简单的替代方法,可以向组件注册KeyListener对象并监视特定键的按下情况。击键允许我们定义一组简单的键,如Shift-Ctrl-P或F4。然后我们可以用组件注册它来激活key,当组件被识别时通知key动作,从而通知ActionListener。
在讨论如何创建键之前,让我们了解一下可以激活键的不同条件,以便添加不同的输入映射。激活注册的键有三个条件,JComponent中的四个常量可以有所帮助。第四种是未定义的状态。表2-4列出了四个可用的常数。
构建密钥
击键类是AWTKeyStroke的子类,没有公开的构造函数。我们可以通过以下方法创建密钥:
公共静态击键getKeyStroke(char keyChar)
公共静态击键getKeyStroke(字符串表示)
公共静态击键getKeyStroke(int keyCode,int modifiers)
公共静态击键getKeyStroke(int keyCode,int modifiers,
布尔onKeyRelease)
公共静态击键getKeyStrokeForEvent(key event key event)
列表中的第一个版本,public static keystrokes get keystrokes(char keystrokes),允许我们从char变量创建键,比如z。
击键空间=keystone . get keystone( Z );
公共静态击键获取击键(字符串表示)版本是最有趣的版本。他可以让我们通过文本字符串指定密钥,例如“控制F4”。的字符串标识符集包括shift、control、meta、alt、button1、button2和button3,以及可以指定的多个标识符。字符串的其余部分来自KeyEvent类的VK_*常量。例如,下面的第三代为Ctrl-Alt-7定义了一个键:
keystone control alt 7=keystone . get keystone( control alt 7 );
公共静态键击获取键击(int keycode,int modifiers)公共静态键击获取键击(int keycode,int modifiers,boolean onkey release)是两种最直接的方法。他允许我们直接指定用于标识符的VK_*常数和输入事件掩码(如果没有标识符,则为0)。未指定时,onKeyRelease为false。
keystone enter=keystone . get keystone(key event。VK _回车,0,真);
KeyStroke shift F4=KeyStroke . get KeyStroke(key event。F4 VK,输入事件。SHIFT _ MASK);
列表中的最后一个版本public static keystoke getkeystokeforevent(KeyEvent key event)直接将特定的key event映射到key stoke。当我们希望允许用户使用按键来激活事件时,这个方法非常有用。我们要求用户为一个事件按下一个键,然后注册KeyEvent,这样下次按下这个键时事件就会被激活。
keystromfrokeyevent=KeyStroke . getkeystrokeforevent(key event);
记录按钮
创建密钥后,我们需要向组件注册它。当我们向组件注册一个键时,我们提供了一个在键被按下(或释放)时被调用的动作。注册提供了从关键到行动的映射。首先,我们通过getInputMap(condition)方法根据焦点激活条件获得组件的相应InputMap。如果没有指定条件,则假定为WHEN_FOCUSED。然后我们在InputMap中添加一个从键到文本字符串的映射:
component.getInputMap()。put(击键,字符串)
如果我们知道现有动作的动作字符串,就可以使用这个字符串;否则,我们将定义这个字符串。然后,我们使用ActionMap将字符串映射到操作:
component . getactionmap . put(string,action)
我们可以通过共享ActionMap实例在组件之间共享操作。在列表2-10的示例中,创建了四个按钮,并且每个按钮注册有不同的键和不同的焦点激活条件。该按钮指示按键激活条件。动作只是输出一条消息并激活按钮标签。
/**
包swingstudy.ch02
导入Java . awt . event queue;
导入Java . awt . gridlayout;
导入Java . awt . event . action event;
导入Java。awt。事件。输入事件;
导入Java。awt。事件。关键事件;
导入javax。挥棒。抽象行动;
导入javax。挥棒。行动;
导入javax。挥棒。动作图;
导入javax。挥棒。输入地图;
导入javax。挥棒。jbutton
导入javax。挥棒。jcomponent
导入javax。挥棒。jframe
导入javax。挥棒。拱顶石;
* @作者联想
公共类KeyStrokeSample {
私有静态最终字符串ACTION _ KEY=该操作
* @param args
公共静态void main(String[] args) {
//TODO自动生成的方法存根
Runnable runner=new Runnable() {
公共无效运行(){
JFrame frame=新JFrame(击键示例);
框架。setdefaultcloseoperation(JFrame .EXIT _ ON _ CLOSE);
JButton button a=new JButton( html中心聚焦英国铁路公司控件alt 7 );
JButton button b=new JButton( html中心焦点/释放br VK _回车);
JButton button c=new JButton( html中心祖先br VK _ F4 SHIFT _ MASK’);
JButton button d=new JButton( html中心窗口br );
动作动作监听器=新抽象动作(){
已执行公共无效操作(操作事件事件){
JButton source=(JButton)事件。getsource();
系统。出去。println(已激活:来源。gettext());
梯形控制alt 7=梯形。get keystone( control alt 7 );
输入映射输入映射=buttona。getinputmap();
inputMap.put(controlAlt7,ACTION _ KEY);
动作图动作图=buttona。getactionmap();
actionMap.put(ACTION_KEY,动作监听器);
梯形输入=梯形。获取keystone(关键事件.VK _回车,0,真);
输入映射=buttonb。getinputmap();
inputMap.put(enter,ACTION _ KEY);
按钮b。setactionmap(动作地图);
按键移动F4=按键。获取击键(按键事件.F4VK,输入事件. SHIFT _ MASK);
输入映射=buttonc。getinputmap(JComponent .WHEN _ ANCESTOR _ OF _ FOCUSED _ COMPONENT);
inputMap.put(shiftF4,ACTION _ KEY);
按钮c。setactionmap(动作地图);
击键空间=击键。获取击键(“”);
输入映射=buttond。getinputmap(JComponent .当_在_聚焦_窗口中);
inputMap.put(space,ACTION _ KEY);
纽扣d。setactionmap(动作地图);
框架。set layout(new GridLayout(2,2));
框架。添加(buttonA);
框架。添加(buttonB);
框架。添加(按钮c);
框架。添加(buttonD);
frame.setSize(400,200);
框架。设置可见(真);
事件队列。稍后调用(runner);
}
图2-7显示了程序运行时的样子。
2.3.4 使用快捷键
摇摆库也可以使用按键对象用于一些内部功能。两个这样的功能为记忆键与快捷键,其工作如下:
在组件记忆键中,标签中的一个字符以下划线出现。当这个字符平台特定的热键组合被按下时,组件就会被激活。例如,在图2-8所示的窗体中按下Alt-A则会在Windows XP平台下选中关于按钮。
菜单快捷键可以在菜单条目不可见的情况下激活条目。例如,在图2-8所示的窗体中按下Ctrl-P将会在文件菜单不可见的情况下选中打印菜单条目。
我们将会在第6章了解更多关于记忆键与快捷键的内容。