逛奔的蜗牛

我不聪明,但我会很努力

   ::  :: 新随笔 ::  ::  :: 管理 ::

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 static ShortcutManager instance = new ShortcutManager();


// 快捷键与事件处理对象键值对

private Map<String, ShortcutListener> listeners;


// 某组件上发生了快捷键列表中的快捷键事件, 如果他的父组件在被忽略组件列表中, 则放弃这个事件.

private Set<Component> ignoredComponents;


// 保存键盘上键与它的ascii码对应

// 如果以某键的ascii码为下标, 数组中此下标的值为true, 说明此键被按下了.

// 当此键被释放开后, 数组中对应的值修改为false

private boolean[] keys;


private ShortcutManager() {

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

}


/**

* 查找此快捷键事件是否要被抛弃

* @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 static ShortcutManager getInstance() {

return instance;

}


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) {

if (0 < keys[i] && keys[i] < this.keys.length) {

sb.append(keys[i]).append(".");

} else {

System.out.println("Key is not valid");

return;

}

}


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

}

}


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

import java.awt.BorderLayout;

import java.awt.event.KeyEvent;


import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;


public class ShortcutTest {

/**

* 测试使用

* @param args

*/

public static void main(String[] args) {

JFrame frame = new JFrame();


JButton button = new JButton("Button");

JTextArea textArea = new JTextArea();

JScrollPane scroller = new JScrollPane(textArea);

frame.getContentPane().add(button, BorderLayout.NORTH);

frame.getContentPane().add(scroller, BorderLayout.CENTER);


// ////////////////////////////////////////////////////////////////////////////////////

// 注册快捷键方法

ShortcutManager.getInstance().addShortcutListener(new ShortcutManager.ShortcutListener() {

public void handle() {

System.out.println("Meta + I");

}

}, KeyEvent.VK_META, KeyEvent.VK_I);


ShortcutManager.getInstance().addShortcutListener(new ShortcutManager.ShortcutListener() {

public void handle() {

System.out.println("Ctrl + Meta + M");

}

}, KeyEvent.VK_CONTROL, KeyEvent.VK_META, KeyEvent.VK_M);


// 测试忽略文本输入里面的快捷键事件, 当按钮得到焦点时, 快捷键事件能正常发生

ShortcutManager.getInstance().addIgnoredComponent(textArea);

// /////////////////////////////////////////////////////////////////////////////////////


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(500, 500);

frame.setVisible(true);

}

}


 


 


posted on 2010-01-31 00:02 逛奔的蜗牛 阅读(3203) 评论(1)  编辑 收藏 引用 所属分类: Java

评论

# re: Java;Swing程序中使用应用程序级的全局快捷键 2014-02-24 12:15 路人
好用,幫了大忙··膜拜了··謝謝分享  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理