使用本机操作系统的默认KeyMap

时间:2009-12-05 15:08:26

标签: java swing look-and-feel keymapping

在Java中,通过使用非默认的系统外观,我们将使用不同的键映射。

例如 我正在使用Mac OS X并使用Substance外观(非默认系统外观)。 效果是我正在丢失我的“元”键以选择所有文本组件 在mac os x中应该是“meta + a”,但是使用Substance我们必须使用“ctrl + a”(以及更多诸如“next word”,“prev word”,“end line”,“begin line”,等等) 所以我们没有使用非默认系统外观(物质外观)的mac os x感觉。

有没有办法使用非默认的系统外观,但使用系统(本机)键映射?

2 个答案:

答案 0 :(得分:1)

解决方法

一个不太优雅的解决方案,你可以尝试通过实现keyPressed方法来添加一个键监听器来覆盖默认的“ctrl + a”行为(请注意以下示例不禁止“ctrl + a”只是添加对“ meta + a“):

@Override
public void keyPressed(final KeyEvent e) {
  // Get the default toolkit shortcut mask ("meta" for OSX).
  int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();

  // You could also check modifiers against KeyEvent.META_MASK...
  if (e.getModifiers() == keyMask && e.getKeyCode() == KeyEvent.VK_A) {
    // Select everything (assumes member of child text component class).
    this.selectAll();

    // We handled this keystroke, 'a' will be ignored by underlying text component.
    e.consume(); 
  }
}

更好的选择是使用inputMaps(请参阅下面的uudashr评论)。


关于根本原因的想法

不幸的是,因为类名表明外观(或 LAF )是外观的组合,即外观,以及“系统行为”,即< EM>感觉。如果你在物质来源周围挖掘,SubstanceLookAndFeel会覆盖摆动的BasicLookAndFeel。它看起来好像是在BasicLookAndFeel中,在initComponentDefaults中设置了违规行为。您应该能够通过调用getDefaults()从LAF获取UIDefault。

这里的问题是:

  • 您希望更改的“系统行为”与您希望保持不变的外观设置混合在一起。
  • 我也一直无法找到任何简单的方法将这些默认值注入LAF级别的实质内容......任何人对此有其他想法吗?

答案 1 :(得分:0)

一种可能性是将META键事件转换为CTRL键事件。因此,当OS X上的用户按下META键时,它将转换为CTRL键。这应该适用于仅在LAF之间交换CTRL和META的关键快捷方式。如果还有其他更复杂的组合,您可以随时进行更复杂的匹配和翻译。下面进行基本翻译的代码,我用一个带有CTRL + O键加速器的JMenuItem测试它,所以现在META + O激活了加速器。

java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {

            public void eventDispatched(AWTEvent event) {
                KeyEvent kev = (KeyEvent) event;
                if (kev.getID() == KeyEvent.KEY_PRESSED || kev.getID() == KeyEvent.KEY_RELEASED || kev.getID() == KeyEvent.KEY_PRESSED) {
                    if ((kev.getModifiersEx() & KeyEvent.META_DOWN_MASK) != 0 && !((kev.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0)) {
                        kev.consume(); // Drop the original event, this is really optional.
                        KeyEvent fake = new KeyEvent(kev.getComponent(),
                                kev.getID(),
                                kev.getWhen(),
                                (kev.getModifiersEx() & ~KeyEvent.META_DOWN_MASK) | KeyEvent.CTRL_DOWN_MASK,
                                kev.getKeyCode(), kev.getKeyChar());
                        java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(fake);
                    }
                }
            }
        }, KeyEvent.KEY_EVENT_MASK);

这将在AWTEvent队列上安装AWTEventListener,并将影响所有关键事件。