在Java事件中处理组合键需要用到KeyStroke这个类,需要先对这个类有一些了解。
在JDK中说,KeyStroke是用来表示键盘的动作的,或者等价的输入设备。KeyStroke 用于定义高级操作事件。不用捕获每个 keystroke 并抛弃不感兴趣的 keystroke,这些重要的 keystroke 会自动在其注册的 Components上启动操作。KeyStroke是不可变的,而且是单例的,必须使用 getKeyStroke工厂方法, 这些工厂方法使得KeyStroke实现能够高效缓存和共享实例。
KeyStroke里面的getKeyStroke有多个实现,可以用String,int和char来构造KeyStroke。
JComponent中有四个常量WHEN_FOCUSED,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,WHEN_IN_FOCUSED_WINDOW,
UNDEFINED_CONDITION.
InputMap根据这个变量的值来觉得在什么范围内触发这个事件,默认是WHEN_FOCUSED。
WHEN_FOCUSED 即该JComponent获得焦点的时候
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 当这个JComponent获得焦点或者ANCESTOR获得焦点的时候
WHEN_IN_FOCUSED_WINDOW 当窗体或者焦点的时候
UNDEFINED_CONDITION 被某些api利用,不知道啥意思
JComponent有两个map,分别是InputMap,ActionMap。
InputMap代表了KeyStroke和Action的映射。
ActionMap代表了Action和actionListener的映射。
当触发热键的时候,会首先检查InputMap中的KeyStroke是否有这个热键,有的话则触发ActionMap中的actionListener,
两个map通过InputMap和ActionMap通过Action那个常量一对一映射。
不过不太明白为什么不让KeyStroke和actionListener直接映射。
下面看一个实例,全面的表现了KeyStroke的功能,代码如下:
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
public class KeyStrokeSample extends JFrame {
private static final long serialVersionUID = 7306881762497576739L;
private static final String ACTION_KEY = "keyPressed";
private JButton buttonA = null;
private JButton buttonB = null;
private JButton buttonC = null;
private JButton buttonD = null;
private Action actionListener = null;
private ActionMap actionMap = null;
public KeyStrokeSample() {
actionListener = ButtonAction.getInstance();
initButtonA();
initButtonB();
initButtonC();
initButtonD();
initFrame();
}
private void initButtonA() {
buttonA = new JButton("<html><center>当该按钮获得焦点时有效<br>热键:Ctrl+Alt+Z");
KeyStroke ctrlAltZ = KeyStroke.getKeyStroke("control alt Z");
buttonA.getInputMap().put(ctrlAltZ, ACTION_KEY);
actionMap = buttonA.getActionMap();
buttonA.getActionMap().put(ACTION_KEY, actionListener);
}
private void initButtonB() {
buttonB = new JButton(
"<html><center>当该按钮获得焦点时有效,触发Release事件<br>热键:Enter");
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true);
buttonB.getInputMap().put(enter, ACTION_KEY);
buttonB.setActionMap(actionMap);
}
private void initButtonC() {
buttonC = new JButton("<html><center>当祖先获得焦点的时候有效<br>热键:Shift+F4");
KeyStroke shiftF4 = KeyStroke.getKeyStroke(KeyEvent.VK_F4,
KeyEvent.SHIFT_MASK);
buttonC.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
shiftF4, ACTION_KEY);
buttonC.setActionMap(actionMap);
}
private void initButtonD() {
buttonD = new JButton("<html><center>当窗口获得焦点的时候有效<br>热键:空格");
KeyStroke space = KeyStroke.getKeyStroke(' ');
buttonD.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(space,
ACTION_KEY);
buttonD.setActionMap(actionMap);
}
private void initFrame() {
this.setTitle("KeyStroke Sample");
initFrameLocation();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setResizable(false);
setLocationRelativeTo(null);
}
private void initFrameLocation() {
Container contentPane = getContentPane();
contentPane.setLayout(new GridLayout(2, 2));
contentPane.add(buttonA);
contentPane.add(buttonB);
contentPane.add(buttonC);
contentPane.add(buttonD);
}
public static void main(String args[]) {
KeyStrokeSample sample = new KeyStrokeSample();
sample.setVisible(true);
}
}
/** button的action处理类 */
class ButtonAction extends AbstractAction {
private static final long serialVersionUID = 2115411141520208211L;
private static ButtonAction action = null;
private ButtonAction() {
}
public void actionPerformed(ActionEvent actionEvent) {
JButton source = (JButton) actionEvent.getSource();
JOptionPane.showMessageDialog(null, "激活:" + source.getText());
}
public static ButtonAction getInstance() {
if (action == null) {
action = new ButtonAction();
}
return action;
}
}
可以根据上面讲的内容读一下代码,比较容易理解。