快捷搜索:

解析Swing中的键盘事件处理

在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 InputMap

focusIm = son.getInputMap();

focusFatherIm = new InputMap();

focusIm.setParent(focusFatherIm);

//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMap

ancestorIm = son.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

//get WHEN_IN_FOCUSED_WINDOW inputMap

windowIm = 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 purpose

TextAction 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 InputMap

focusIm = son.getInputMap();

focusFatherIm = new InputMap();

focusIm.setParent(focusFatherIm);

//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMap

ancestorIm = son.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

//get WHEN_IN_FOCUSED_WINDOW inputMap

windowIm = son.getInputMap(WHEN_IN_FOCUSED_WINDOW);

//put the keyStroke to the 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");

//get the actionMap

am = 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 backgracolor

Object 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();

}

}

您可能还会对下面的文章感兴趣: