5

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

例如,我使用 Mac OS X 并使用 Substance 外观(非默认系统外观)。效果是我失去了我的“meta”键来全选文本组件在mac os x中应该是“meta + a”,但是使用Substance我们必须使用“ctrl + a”(还有更多,比如“下一个单词”、“上一个单词”、“结束行”、“开始行”等)所以我们没有使用非默认系统外观(物质外观)的 mac os x 感觉。

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

4

2 回答 2

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)是外观(即外观)和“系统行为”(即感觉)的组合。如果您在物质源周围进行挖掘,则SubstanceLookAndFeel会覆盖Swing附带的BasicLookAndFeel 。看起来好像在 BasicLookAndFeel 中,违规行为是在 initComponentDefaults 中设置的。您应该能够通过调用 getDefaults() 从 LAF 获取 UIDefaults。

这里的问题是:

  • 您希望更改的“系统行为”与您希望保持不变的外观设置混合在一起。
  • 我也找不到任何简单的方法将这些默认值注入到 LAF 级别的实质中......有人对此有其他想法吗?
于 2009-12-06T08:23:03.553 回答
0

一种可能性是将 META 键事件转换为 CTRL 键事件。因此,当 OS X 上的用户按下 META 键时,它会被转换为 CTRL 键。这应该适用于只有 CTRL 和 META 在 LAF 之间交换的快捷键。如果还有其他更复杂的组合,您总是可以进行更复杂的匹配和翻译。下面是做基本翻译的代码,我用一个 JMenuItem 测试了它,它的快捷键是 CTRL+O,所以现在 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,并将影响所有关键事件。

于 2009-12-30T18:48:48.430 回答