在Java Swing编程过程中,经常需要处理键盘事件,例如处理快捷键等。这里就介绍如何定义键盘事件,以及如何处理这些事件。

在jdk1.2中,分别针对Jcomponent和Text类的对象定制了不同的处理键盘事件的方法:在Jcomponent中,定义了registerKeyboardAction方法,使用这个方法来将需要处理的键盘事件以及处理事件的行为绑定在一起。Text类中具有keymap对象,同Jcomponent中的处理方法类似,这个对象保存着需要处理的键盘事件和对应的行为。

而在jdk1.3中,使用一种新的方法来处理键盘事件,它将jdk1.2的两种方法整合在一起。不需要区分被处理的是Jcomponent还是Text类型的组件。它定义了两个新的类:InputMap和ActionMap。他们均是简单的表或映射。一个InputMap将一个Keystroke对应到一个对象,ActionMap将一个对象对应到一个行为(Action)。通常InputMap中KeyStroke所对应的对象是一个字符串,通过这个字符串可以在ActionMap中查找到相应的行为。

InputMap和ActionMap中均有put方法。InputMap的put方法可以将Keystroke对应到一个对象,而ActionMap的put方法可以将一个对象对应到一个行为。

在每一个Jcomponent组件中,会有三个缺省的InputMap和一个缺省的ActionMap。他们可以通过调用getInputMap(int condition)和getActionMap()得到。三个InputMap分别是当组件本身拥有焦点时的InputMap(WHEN_FOCUSED),当组件的祖先拥有焦点时的InputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)和组件所在的窗体具有焦点时的InputMap(WHEN_IN_FOCUSED_WINDOW)(括号内表示为了得到这些InputMap,应该在getInputMap中设置的参数)。以下分别说明这三种InputMap:

1. 组件本身拥有焦点时的InputMap:当组件拥有焦点时,键盘按键按下,则java在这个InputMap中查找键盘事件所对应的KeyStroke对象。

2. 组件的祖先拥有焦点时的InputMap:当组件的祖先拥有焦点时,键盘按键按下,则java查找这个InputMap。

3. 组件所在的窗口拥有焦点时的InputMap:当组件所在的窗口具有焦点时,键盘按键按下,则java查找这个InputMap。

当一个键被按下,这个事件被转化成一个KeyStroke对象,java会查找这个Jcomponent的相应InputMap(例如,当组件的祖先具有焦点时,java就查找这个Jcomponent的祖先拥有焦点的InputMap)中是否有这个KeyStroke,如果有,取出它所对应的对象(通常是字符串),利用这个对象在这个Jcomponent的ActionMap中查找,如果找到对应的行为(Action),则java执行这个行为的actionPerformed方法(随后介绍这个方法)。从而达到处理键盘事件的目的。

每一个InputMap可以具有parent属性,这个属性的值是一个InputMap。当在一个InputMap中查找不到键盘事件的KeyStroke时,java会自动在它的parent属性指定的InputMap中查找,依次向上查找,直至找到。使用parent的好处是:当有一些固定的,不希望用户进行改动的键盘映射可以存放在parent属性所指定的InputMap中,从而避免被意外修改;另外可以将多个Jcomponent的缺省InputMap设置具有相同的parent,使得可以共享一些键盘绑定的设置。可以通过InputMap类的setparent()方法设置它的parent属性。ActionMap也具有相同的parent属性,使用方法也相同。

以上是如何将一个键盘事件对应到一个行为,以下就简单介绍行为(Action)。

行为是一个实现了Action接口的类。在Action接口中定义了7个方法。其中最关键的是actionPerformed()方法。这个方法描述了这个行为的具体操作过程。其他几个方法包括setEnabled,isEnabled,putValue,getValue,addPropertyChangeListener,和removePropertyChangeListener方法。他们分别用来设置行为是否可用、判断行为可用的状态、设置和取得行为的一些属性,最后两个方法用来允许其他对象在行动对象的属性发生变化后得到通知。

通常我们使用一个实现了Action接口的大部分方法的抽象类AbstractAction类作为基类,重载actionPerformed方法以实现我们的行为。

我们用一个例子来具体说明如何进行实际的操作。

首先编写一个具体的行为,对指定的键盘事件进行处理:

public class TextAction extends AbstractAction{private String a;public TextAction(String a){ this.a = a; }public void actionPerformed(ActionEvent parm1){String b = parm1.getActionCommand(); //得到行为的命令字符串System.out.println("command="+b);System.out.println("prompt="+this.a);}}

建立四个TextAction对象:

TextAction whenFocusSon = new TextAction("focus son");

TextAction whenFocusFather = new TextAction("focus father");

TextAction window = new TextAction("window");

TextAction ancestor = new TextAction("ancestor");

随后,在一个窗体中加入两个面板,名为sonPanel和parentPanel,使得parentPanel是sonPanel的祖先。并在sonPanel中加入一个名为son的button,在parentPanel中加入名为parent的button。在fatherPanel外加入几个button。

得到son组件的三个InputMap,并创建一个名为focusFatherIm的InputMap,使得这个InputMap成为focusIm的parent:

//get default inputMap (when focus inputmap) and set a parent InputMapfocusIm = son.getInputMap();focusFatherIm = new InputMap();focusIm.setParent(focusFatherIm);//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMapancestorIm = son.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);//get WHEN_IN_FOCUSED_WINDOW inputMapwindowIm = son.getInputMap(WHEN_IN_FOCUSED_WINDOW);//在这些InputMap中分别加入键盘绑定:focusIm.put(KeyStroke.getKeyStroke('f'),"actionFocusSon");focusFatherIm.put(KeyStroke.getKeyStroke('F'),"actionFocusFather");ancestorIm.put(KeyStroke.getKeyStroke('a'),"actionAncestor");windowIm.put(KeyStroke.getKeyStroke('w'),"actionWindow");//得到son组件的缺省的ActionMap,并将已经建立的行为与特定的对象(字符串)进行绑定:am = son.getActionMap();am.put("actionFocusSon",whenFocusSon);am.put("actionFocusFather",whenFocusFather);am.put("actionAncestor",ancestor);am.put("actionWindow",window);

运行程序及其相应结果:

1. 单击son按钮,这时如果按下'f','F','a','w',程序均会有相应的输出。这是因为,此时的焦点在son按钮上,而son按钮组件的三个InputMap都是有效的。所以他们对应的事件都会发生。

2. 单击parent按钮,这时按下'w',程序会有相应的输出。而按下'f','F','a',程序没有反应。这是因为parent按钮具有焦点,这个按钮不是son按钮的祖先,而son所在的窗口具有焦点,所以只有组件所在窗口具有焦点的InputMap是有效的。

3. 单击其他的按钮(parentPanel外的按钮),这时按下'w',程序会有相应的输出。而按下'f','F','a',程序没有反应。这是因为这些按钮具有焦点,他们不是son按钮的祖先,而son所在的窗口具有焦点,所以只有组件所在窗口具有焦点的InputMap是有效的。

附:主要程序代码:

import java.awt.*;import javax.swing.*;import com.borland.jbcl.layout.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import com.sun.java.swing.plaf.motif.*;public class EventPanel extends JPanel implements ActionListener{JButton btnYellow = new JButton();JButton btnBlue = new JButton();JButton btnRed = new JButton();JPanel parentPanel = new JPanel();JPanel sonPanel = new JPanel();XYLayout xYLayout1 = new XYLayout();JButton son = new JButton();JButton parent = new JButton();public EventPanel(){try{jbInit();}catch(Exception ex){ ex.printStackTrace(); }}void jbInit() throws Exception{btnYellow.setText("Yellow");btnYellow.setBounds(new Rectangle(35, 23, 97, 29));this.setLayout(null);btnBlue.setBounds(new Rectangle(154, 21, 97, 29));btnBlue.setText("Blue");btnRed.setBounds(new Rectangle(272, 24, 97, 29));btnRed.setText("Red");parentPanel.setBorder(BorderFactory.createRaisedBevelBorder());parentPanel.setBounds(new Rectangle(27, 68, 358, 227));parentPanel.setLayout(xYLayout1);sonPanel.setBorder(BorderFactory.createLoweredBevelBorder());son.setText("son");parent.setText("parent");this.add(btnYellow, null);this.add(btnBlue, null);this.add(btnRed, null);this.add(parentPanel, null);parentPanel.add(sonPanel, new XYConstraints(58, 22, 229, 125));sonPanel.add(son, null);parentPanel.add(parent, new XYConstraints(150, 167, -1, -1));btnYellow.addActionListener(this);btnRed.addActionListener(this);btnBlue.addActionListener(this);InputMap focusIm,focusFatherIm,ancestorIm,windowIm;ActionMap am;//create four TextAction for diff purposeTextAction whenFocusSon = new TextAction("focus son");TextAction whenFocusFather = new TextAction("focus father");TextAction window = new TextAction("window");TextAction ancestor = new TextAction("ancestor");//get default inputMap (when focus inputmap) and set a parent InputMapfocusIm = son.getInputMap();focusFatherIm = new InputMap();focusIm.setParent(focusFatherIm);//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMapancestorIm = son.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);//get WHEN_IN_FOCUSED_WINDOW inputMapwindowIm = son.getInputMap(WHEN_IN_FOCUSED_WINDOW);//put the keyStroke to the InputMapfocusIm.put(KeyStroke.getKeyStroke('f'),"actionFocusSon");focusFatherIm.put(KeyStroke.getKeyStroke('F'),"actionFocusFather");ancestorIm.put(KeyStroke.getKeyStroke('a'),"actionAncestor");windowIm.put(KeyStroke.getKeyStroke('w'),"actionWindow");//get the actionMapam = son.getActionMap();am.put("actionFocusSon",whenFocusSon);am.put("actionFocusFather",whenFocusFather);am.put("actionAncestor",ancestor);am.put("actionWindow",window);}public void actionPerformed(ActionEvent e){//this code is used to change the backgracolorObject source=e.getSource();Color color=null;//=getBackground();if (source==btnYellow) color=Color.yellow;else if (source==btnRed) color = Color.red;else if (source == btnBlue) color = Color.blue;setBackground(color);repaint();}}
本文转自博客园执着的笨蛋的博客,原文链接:Java Swing中键盘事件的处理,如需转载请自行联系原博主。

Java Swing中键盘事件的处理相关推荐

  1. Java Swing事件处理——键盘事件及监听处理 KeyListener 按键测试

    代码如下 package com.liuyanzhao;import java.awt.Button;import java.awt.Color;import java.awt.Frame;impor ...

  2. Java语言学习--Swing中Button事件监听

    1 前言 今天在使用Java Swing中的JButton的事件触发机制时遇到了许多问题,简单的了解了一下. 2 事件监听机制 事件监听的机制如下图所示分析. 3 代码分析 3.1 分步解析 1.事件 ...

  3. java swing 注册事件_比较Java Swing中三种注册事件的方法

    Swing 是目前Java中不可缺少的窗口工具组,是建立图形化用户界面(GUI)程序的强大工具.Java Swing组件自动产生各种事件来响应用户行为.Java将事件封装成事件类,并且为每个事件类定义 ...

  4. swingworker_使用SwingWorker的Java Swing中的多线程

    swingworker 如果要使用Swing用J​​ava编写桌面或Java Web Start程序,您可能会觉得需要通过创建自己的线程在后台运行某些程序. 没有什么可以阻止您在Swing中使用标准的 ...

  5. 使用SwingWorker的Java Swing中的多线程

    如果要使用Swing用J​​ava编写桌面或Java Web Start程序,您可能会觉得需要通过创建自己的线程在后台运行某些东西. 没有什么可以阻止您在Swing中使用标准的多线程技术,并且需要遵循 ...

  6. Java处理敲击键盘事件 Etch-A-Sketch玩具实现 光标画笔画图程序 Java核心技术

    Java处理敲击键盘事件 Etch-A-Sketch玩具实现 光标画笔画图程序 Java核心技术 source code: package com.sunnyykn.chapter08; import ...

  7. Java Swing中的聊天气泡

    本文将向您解释"如何在Java swing应用程序中绘制聊天气泡?" 聊天气泡与呼出气泡或思想气泡相同. 今天,大多数聊天应用程序都以这种格式显示转换,因此本文将帮助您在用Java ...

  8. Java Swing中JFreeChart构建双纵轴(双Y轴)图表的使用纪要

    背景 项目应用中整理纪要,用于参数说明.后抽部分简码以用例,特此纪要! 问题 Java Swing中JFreeChart如何构建双纵轴(双Y轴)图表 说明 JFreeChart是一个工厂类,是Swin ...

  9. java中的事件都继承自_下列说法中不正确的是()。A.Java语言中的事件都是继承自Java.awt.AW-TEvent类B.AWTEve...

    下列说法中不正确的是().A.Java语言中的事件都是继承自Java.awt.AW-TEvent类B.AWTEve 更多相关问题 [单选] 月经后期而至,量少,色淡,质清稀,少腹隐痛,喜暖喜按,脉沉迟 ...

最新文章

  1. mysql5.7用declare声明失败_我可能会失败,但我不会一直失败。
  2. 20165239其米仁增3
  3. 机器学习和深度学习笔记(Matlab语言实现)
  4. Linux系统中/dev/mtd与/dev/mtdblock的区别
  5. 等概率随机函数的实现(对立事件的产生)
  6. 计算机博士后流动站有哪些,全国博士后流动站一览表.docx
  7. 如何查计算机电源功率,怎么看电脑电源功率
  8. [转]Linux启动界面切换:图形界面-字符界面
  9. 前端 html h5 移动端 手机端 仿ios左滑删除效果
  10. admin is not in the sudoers file. This incident will be reported
  11. django和php学哪个好,哪个更适合我的项目:Django、Plone、php还是rubyonrails
  12. 在 MATLAB 或 Python 中使用 ZOS-API 进行光线追跡的批次处理
  13. 配置 HTTP 代理(WIN10)、SOCKS 代理(WIN10)和编写 PAC 自动配置脚本
  14. dva 的一些特殊的写法
  15. 零基础小白,如何从零开始搭建网站?(详细步骤)
  16. VMware安装、启动虚拟机报错:无法打开内核设备“\\.\VMCIDev\VMX”: 操作成功完成。是否在安装 VMware Workstation 后重新引导?
  17. 微信端中的企业号、订阅号、服务号之前的区别
  18. Kitti数据集简介
  19. Tekton系列之实践篇-由Jenkins改成Tekton
  20. 关于视频变速播放软件

热门文章

  1. 今天在群里面讨论了驱动机制的学习
  2. 第 22 章 Beta
  3. android 渐变展示启动屏
  4. C# textBox框实现输入像百度搜索出现下拉列表的格式
  5. 0927_C/C++笔试题_10:16道c语言面试例子【2】
  6. Fatal error: Cannot redeclare db_connect() 错误
  7. Reporting Services Internal Error(诡异的问题)-【转载】
  8. Android 仿美团网,大众点评购买框悬浮效果之修改版
  9. android-- dp px sp长度单位的区别
  10. Green Plum测试报告