2008-09-19 3 views
27

Я хотел бы создать ярлык приложения для широкого спектра приложений Java Swing. Зацикливание всех компонентов и добавление ярлыка на каждый, связанные с фокусом побочные эффекты, и похоже на решение грубой силы.Application wide keyboard shortcut - Java Swing

У кого-нибудь есть более чистое решение?

ответ

20

Установите пользовательский KeyEventDispatcher. Класс KeyboardFocusManager также является хорошим местом для этой функции.

KeyEventDispatcher

37

Для каждого окна, используйте JComponent.registerKeyboardAction с условием WHEN_IN_FOCUSED_WINDOW. В качестве альтернативы можно использовать:

JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command); 
JComponent.getActionMap().put(command,action); 

как описано в registerKeyboardAction API docs.

+0

+1 Лучший, самый простой ответ, который я нашел. Я продолжу это x1000 – 2011-10-26 16:05:05

+3

x1001 будет лучше, таким образом, он, по крайней мере, получит преимущество. – Epaga 2012-04-17 09:46:16

+0

@Epaga Или 999 раз – 2013-09-01 15:50:58

6

Если у вас есть меню, вы можете добавить глобальные сочетания клавиш для пунктов меню:

JMenuItem item = new JMenuItem(action); 
    KeyStroke key = KeyStroke.getKeyStroke(
     KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK); 
    item.setAccelerator(key); 
    menu.add(item); 
13

Для людей интересно (как я), как использовать KeyEventDispatcher, вот пример, который я поставил вместе. Он использует HashMap для хранения всех глобальных действий, потому что мне не нравятся большие конструкции if (key == ..) then .. else if (key == ..) then .. else if (key ==..) ...

/** map containing all global actions */ 
private HashMap<KeyStroke, Action> actionMap = new HashMap<KeyStroke, Action>(); 

/** call this somewhere in your GUI construction */ 
private void setup() { 
    KeyStroke key1 = KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK); 
    actionMap.put(key1, new AbstractAction("action1") { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println("Ctrl-A pressed: " + e); 
    } 
    }); 
    // add more actions.. 

    KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
    kfm.addKeyEventDispatcher(new KeyEventDispatcher() { 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent e) { 
     KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e); 
     if (actionMap.containsKey(keyStroke)) { 
     final Action a = actionMap.get(keyStroke); 
     final ActionEvent ae = new ActionEvent(e.getSource(), e.getID(), null); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
      a.actionPerformed(ae); 
      } 
     }); 
     return true; 
     } 
     return false; 
    } 
    }); 
} 

Использование SwingUtils.invokeLater(), может быть, не нужно, но это, вероятно, хорошая идея, чтобы не блокировать глобальный цикл событий.

-1

Используйте следующий фрагмент кода

ActionListener a=new ActionListener(){ 
    public void actionPerformed(ActionEvent ae) 
    { 
    // your code 
    } 
}; 
getRootPane().registerKeyboardAction(a,KeyStroke.getKeyStroke("ctrl D"),JComponent.WHEN_IN_FOCUSED_WINDOW); 

Заменить "Ctrl D" с ярлыком вы хотите.

1

Немного упрощенный пример:

KeyboardFocusManager keyManager; 

keyManager=KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
keyManager.addKeyEventDispatcher(new KeyEventDispatcher() { 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent e) { 
    if(e.getID()==KeyEvent.KEY_PRESSED && e.getKeyCode()==27){ 
     System.out.println("Esc"); 
     return true; 
    } 
    return false; 
    } 

});