【问题标题】:Application wide keyboard shortcut - Java Swing应用程序范围的键盘快捷键 - Java Swing
【发布时间】:2008-09-19 06:54:03
【问题描述】:

我想为 Java Swing 应用程序创建一个应用程序范围的键盘快捷键。 循环遍历所有组件并在每个组件上添加快捷方式,具有与焦点相关的副作用,并且似乎是一种蛮力解决方案。

谁有更清洁的解决方案?

【问题讨论】:

    标签: java swing shortcut keystroke


    【解决方案1】:

    对于每个窗口,使用JComponent.registerKeyboardAction,条件为WHEN_IN_FOCUSED_WINDOW。或者使用:

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

    registerKeyboardAction API docs 中所述。

    【讨论】:

    • +1 我找到的最好、最简单的答案。我会赞成这个 x1000
    • 但是JFrame没有getInputMap或者getActionMap方法
    • @Can'tTell JFrame 不是 JComponent。这些方法需要在顶级窗口中的组件上调用。
    • 第一个解决方案的示例:window.getRootPane().registerKeyboardAction(save.getActionListeners()[0], KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);save 替换为 JButton 的名称,将 window 替换为 JFrame 的名称。
    【解决方案2】:

    安装自定义 KeyEventDispatcher。 KeyboardFocusManager 类也是实现此功能的好地方。

    KeyEventDispatcher

    【讨论】:

      【解决方案3】:

      对于想知道(像我一样)如何使用 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(),但最好不要阻塞全局事件循环。

      【讨论】:

      • 不是最简单的解决方案,但绝对是最优雅、最可靠的解决方案。
      【解决方案4】:

      当你有一个菜单时,你可以为菜单项添加全局键盘快捷键:

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

      【讨论】:

        【解决方案5】:

        一个简单的例子:

        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】:

          使用下面这段代码

          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”。

          【讨论】:

          • 不,那是过时的 api(从 jdk 1.2 或 1.3 开始被 actionMap/inputMap 取代 - 回到石器时代)
          • @kleopatra 嗯。感谢您的评论。我想知道原因。没找到!
          • 不太明白 - 什么原因?
          • 为什么 registerKeyboardAction() 过时了
          • 请参阅 javadoc (JComponent.registerKeyboardAction(java.awt.event.ActionListener, java.lang.String, javax.swing.KeyStroke, int)):此方法现已过时,请使用getActionMap() 和 getInputMap() 的组合用于类似的行为。
          猜你喜欢
          • 2010-10-02
          • 1970-01-01
          • 1970-01-01
          • 2012-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-21
          相关资源
          最近更新 更多