快捷键注册代码(来自互联网,稍作改进)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cashiersystem;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class ShortcutManager implements AWTEventListener {
// 快捷键与事件处理对象键值对
private Map<String, ShortcutListener> listeners;
// 某组件上发生了快捷键列表中的快捷键事件, 如果他的父组件在被忽略组件列表中, 则放弃这个事件.
private Set<Component> ignoredComponents;
// 保存键盘上键与它的ascii码对应
// 如果以某键的ascii码为下标, 数组中此下标的值为true, 说明此键被按下了.
// 当此键被释放开后, 数组中对应的值修改为false
private boolean[] keys;
public ShortcutManager() {
System.out.println("init hotKey manager.....");
keys = new boolean[256];
ignoredComponents = new HashSet<Component>();
listeners = new HashMap<String, ShortcutListener>();
// 只关心键盘事件
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
}
/**
* 有键盘事件发生
*/
public void eventDispatched(AWTEvent event) {
if (event.getClass() == KeyEvent.class) {
KeyEvent ke = (KeyEvent) event;
if (ke.getID() == KeyEvent.KEY_PRESSED) {
keys[ke.getKeyCode()] = true;
// 查找快捷键对应的处理对象, 然后调用事件处理函数
String shortcut = searchShortcut();
ShortcutListener l = listeners.get(shortcut);
if (l != null && !isIgnored(event)) {
l.handle();
}
} else if (ke.getID() == KeyEvent.KEY_RELEASED) {
keys[ke.getKeyCode()] = false;
}
}
}
protected String searchShortcut() {
// 每个键之间用一个"."来隔开.
// 例如ctr + x的对应值为"17.88."
StringBuilder shortcut = new StringBuilder();
for (int i = 0; i < keys.length; ++i) {
if (keys[i]) {
shortcut.append(i).append(".");
}
}
// System.out.println(shortcut.toString());
return shortcut.toString();
}
//清空当前注册的快捷键
public void clearAll(){
listeners = new HashMap<String, ShortcutListener>();
System.out.println("clear all hot keys");
}
/**
* 查找此快捷键事件是否要被抛弃
*
* @param event
* @return
*/
protected boolean isIgnored(AWTEvent event) {
if (!(event.getSource() instanceof Component)) {
return false;
}
boolean ignored = false;
for (Component com = (Component) event.getSource(); com != null; com = com.getParent()) {
if (ignoredComponents.contains(com)) {
ignored = true;
break;
}
}
return ignored;
}
public void removeShortcutListener(ShortcutListener l) {
String tempKey = null;
for (Map.Entry<String, ShortcutListener> e : listeners.entrySet()) {
if (e.getValue().equals(l)) {
tempKey = e.getKey();
}
}
listeners.remove(tempKey);
}
public void addShortcutListener(ShortcutListener l, int... keys) {
// 快捷键的对应值按它们的键顺序大小来进行创建
StringBuilder sb = new StringBuilder();
Arrays.sort(keys);
for (int i = 0; i < keys.length; ++i) {
sb.append(keys[i]).append(".");
}
String shortcut = sb.toString();
// 如果还不存在, 则加入
if (listeners.containsKey(shortcut)) {
System.out.println("The shourt cut is already used.");
} else {
listeners.put(shortcut, l);
}
}
public void addIgnoredComponent(Component com) {
ignoredComponents.add(com);
}
public void removeDiscardComponent(Component com) {
ignoredComponents.remove(com);
}
public static interface ShortcutListener {
void handle();
}
}
在主窗口中应用:
首先设置一个标记位来记录是否有其他窗口打开过:
//标记其他窗口是否出现过,如果出现说,置为true,当监听器监听到该窗口获取焦点后,会根据该值重新注册快捷键
private boolean isDealFrameOpened = false;
在主窗口中注册快捷键:
private void hotKeyManager(){
stm = new ShortcutManager();
//ESC键:退出登录
stm.addShortcutListener(new ShortcutManager.ShortcutListener() {
@Override
public void handle() {
logout();
}
}, new cashiersystem.Util().getShortCut("ESC"));
}
为主窗口添加监听:为了监听其他窗口关闭后主窗口重新获得焦点
//窗口获得焦点事件
private void formWindowGainedFocus(java.awt.event.WindowEvent evt) {
// TODO add your handling code here:
if(isDealFrameOpened){
isDealFrameOpened = false;
setShortcut(); //重新加载快捷键
}
}
在出窗口打开子窗口代码,此时要清空主窗口已经注册过的快捷键,这样如果两个窗口有同样的快捷键,就不会冲突了
//查看本地历史订单
private void getLocalDeal(){
stm.clearAll(); //清空已注册的快捷键
LocalDealFrame lf = new LocalDealFrame(); //子窗口
isDealFrameOpened = true;
lf.setVisible(true); //将标记设为true,当子窗口关闭时,会触发自动注册主窗口快捷键的监听
}