29

Вопрос по keystroke, shortcut, swing, java – Сочетание клавиш широкого применения - Java Swing

Я хотел бы создать комбинацию клавиш для приложения Java Swing. Цикл по всем компонентам и добавление ярлыка для каждого, имеет побочные эффекты, связанные с фокусом, и кажется грубым решением проблемы.

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

  • Не самое простое решение, но определенно самое элегантное и надежное.

    от
  • @kleopatra Хмм. Спасибо за комментарий. Я хочу знать причину. Я не нашел это!

    от
  • Почему registerKeyboardAction () устарел

    от
  • Для примера первого решения:window.getRootPane().registerKeyboardAction(save.getActionListeners()[0], KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); замещатьsave с именем вашего JButton, иwindow с именем вашего JFrame.

    от
  • нет, это устаревший API (заменен actionMap / inputMap начиная с jdk 1.2 или 1.3 - в далеком прошлом в каменном веке)

    от
  • x1001 был бы лучше, таким образом он, по крайней мере, получил бы повышение.

    от
  • Пожалуйста, посмотрите javadoc (JComponent.registerKeyboardAction (java.awt.event.ActionListener, java.lang.String, javax.swing.KeyStroke, int)): этот метод теперь устарел, используйте комбинацию getActionMap () и getInputMap () для похожего поведения.

    от
  • не совсем понимаю - причина чего?

    от
  • @ Может & APOS; tTellJFrame это неJComponent, Эти методы необходимо вызывать для компонентов в окне верхнего уровня.

    от
  • Но у JFrame нет метода getInputMap или getActionMap

    от
  • +1 Лучший, самый простой ответ, который я нашел. Я буду голосовать за это x1000

    от
6 ответов
  • -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" с ярлыком, который вы хотите.

  • 39

    Для каждого окна используйте

    JComponent.registerKeyboardAction с условиемWHEN_IN_FOCUSED_WINDOW, Альтернативно используйте:

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

    как описано вregisterKeyboardAction API документы.

  • 20

    Установите пользовательский KeyEventDispatcher. Класс KeyboardFocusMan

    ager также является хорошим местом для этой функциональности.

    KeyEventDispatcher

  • 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;
      }
    
    });
    

  • 6

    Когда у вас есть меню

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

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

  • 14

    Для людей

    интересующихся (как и я), как использовать 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 (), возможно, не является необходимым, но, вероятно, будет хорошей идеей не блокировать глобальный цикл обработки событий.