(个人笔记) swing 设置程序级快捷键 和 窗口集快捷键

本文介绍了如何在Swing程序中设置全局及窗口级别的快捷键。通过一段代码展示,强调了在多个窗口之间切换时如何避免快捷键冲突的问题,确保每个窗口的快捷键独立有效。

快捷键注册代码(来自互联网,稍作改进)


/*
 * 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,当子窗口关闭时,会触发自动注册主窗口快捷键的监听
        
        
    }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值