谢谢你们的建议,伙计们。这次讨论使我找到了几种可行的解决方案。
首先,解决在没有实际使用快捷键的情况下显示快捷“提示”文本的问题。只需像往常一样将快捷键添加到 Action/JMenuItem(这将为您提供提示文本),然后在添加快捷键后立即取消绑定。一种简单(但不是唯一)的方法是创建 JMenuItem 的子类,并覆盖单个方法:
@Override public void setAccelerator(KeyStroke keyStroke) {
super.setAccelerator(keyStroke);
getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, "none");
}
瞧!一个无功能的快捷键,菜单项上的提示文本仍然完好无损。
但是,对我最初的问题的更好解决方案是更改所有快捷键的行为,以便当键盘焦点位于文本组件内时它们不会触发。 据我所知,这确实是唯一一种(未修改的)快捷键(如 SPACE)会与现有窗口组件的行为发生冲突的情况。第二个解决方案更费力,但更好,因为它允许我删除所有其他用于处理快捷键的自定义代码,而无需将其安装在 JMenuBar 中。
相反,我可以在 swing 中使用常规的快捷键架构(即将它安装在 JMenuBar 或 Action 对象中),只需进行一次小的修改:
这部分再次位于 JMenuItem 的自定义子类中:
/** {@inheritDoc} */
@Override public void setAccelerator(KeyStroke keyStroke) {
super.setAccelerator(keyStroke);
if (doClickAction_ == null) {
doClickAction_ = new DoClickAction(getActionMap().get("doClick"));
getActionMap().put("doClick", doClickAction_);
}
}
这是我的 JMenuItem 子类中的一个新的私有内部类:
/**
* 这个动作包装了这个菜单项的原始“doClick”动作,
* 修改它,使其仅在键盘焦点不在任何位置时触发
* 文本区域或文本字段的种类。
*
* 这允许将加速键添加到 {@link IMenuItem}s,
* 但用户仍然可以将这些键输入到文本组件中,而无需
* 触发加速键行为。
*/
私有静态类 DoClickAction 扩展 AbstractAction {
// 原始动作,即我们正在包装
私人最终动作 doClickAction_;
DoClickAction( 动作 doClickAction ) {
如果(doClickAction == null){
抛出新的 IllegalArgumentException();
}
doClickAction_ = doClickAction;
}
@Override public void actionPerformed(ActionEvent e) {
最终的 KeyboardFocusManager kfm =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
if ( kfm.getFocusOwner() instanceof JTextComponent == false ) {
doClickAction_.actionPerformed(e);
}
}
}