Java 如何检测JComboBox中的TAB键按下?

Java 如何检测JComboBox中的TAB键按下?,java,swing,jcombobox,key-bindings,Java,Swing,Jcombobox,Key Bindings,我试图找出当用户按下tab键或在组件区域外单击鼠标时,如何检测JComboBox是否失去焦点 将FocusListener添加到JComboBox的编辑器组件对我没有帮助,因为我无法确定用户是否使用了鼠标或通过tab键移动了焦点。任何想法都将不胜感激 编辑1: 我试图实现的是: 假设用户下拉列表(显示JComboBox弹出菜单),并通过光标键进行导航 案例1:用户按tab键。在本例中,我希望从项目中删除一些信息,并仅显示一些部分 案例2:用户在弹出菜单区域外用鼠标单击(这里我们有子类,但它们都

我试图找出当用户按下tab键或在组件区域外单击鼠标时,如何检测JComboBox是否失去焦点

将FocusListener添加到JComboBox的编辑器组件对我没有帮助,因为我无法确定用户是否使用了鼠标或通过tab键移动了焦点。任何想法都将不胜感激

编辑1: 我试图实现的是:

  • 假设用户下拉列表(显示JComboBox弹出菜单),并通过光标键进行导航
  • 案例1:用户按tab键。在本例中,我希望从项目中删除一些信息,并仅显示一些部分
  • 案例2:用户在弹出菜单区域外用鼠标单击(这里我们有子类,但它们都属于同一类别)。在本例中,我希望更改JComboBox以显示先前编辑的项,而不是用户导航的项
  • 还有其他几种情况(鼠标项拾取、回车键、转义等)。我可以很容易地处理这些事件,但检测选项卡是很棘手的,因为我无法捕获这个事件,因为它是由FocusManager处理的
编辑2: 似乎我必须使用
setFocusTraversalKeysEnabled(false)
在按下TAB键时获得通知,当我捕获该事件时,我应该手动转移焦点。。。我不喜欢这个解决方案,但到目前为止,这是我能想到的最好的解决方案

解决方案:

下面的一段Java代码实际上解决了我的问题。正如我在edit2中所写的,最简单的解决方案是禁用焦点遍历。我厚颜无耻地借用了克利奥帕特拉的密码,现在一切正常了


感谢所有参与讨论的人

假设您在松开焦点之前按下了鼠标(或键)。所以,听一听所有的键盘和鼠标的点击,在失去焦点之前最后一次使用的就是罪魁祸首


当启动focuslost时,您可以在窗口的任何部分检查鼠标或按键时设置的变量。此变量仅记录上次按下的鼠标和/或键。当然,您必须捕获所有鼠标和按键,因为单击任何小部件都会使您失去焦点。

据我所知,您的问题有两个不同的问题

  • 导航时不要提交值
  • 接管对TAB的反应
如果是,答案是

  • 配置组合,使其认为它是CellEditor的编辑组件
  • 禁用组合的默认遍历键,并使用自定义绑定接管
代码:

    final JComboBox simpleBox = new JComboBox(Locale.getAvailableLocales());
    // this line configures the combo to only commit on ENTER 
    // or selecting an item from the list
    simpleBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
    //
    // simpleBox.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
    //     Collections.EMPTY_SET);
    // just noticed the OPs edit - following indeed is easier to disable _all_ traversal
    // keys with one statement
    simpleBox.setFocusTraversalKeysEnabled(false);

    Action myAction = new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            LOG.info("got it!");
            simpleBox.transferFocus();
        }

    };
    simpleBox.getActionMap().put("tab-action", myAction);
    simpleBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
       .put(KeyStroke.getKeyStroke("TAB"), "tab-action");

“任何想法都将不胜感激。”解释此功能的用例。通过了解,您试图为最终用户提供什么功能?Andrew,感谢您的回复,请参阅编辑1。FocusLost仍然被触发,我无法确定它是在用户按TAB键时触发的,还是在用户单击某个位置时触发的。。。这就是问题的本质。是的,当focuslost被触发时,你会检查你在按下鼠标或键时在窗口的任何部分设置的变量。此变量仅记录上次按下的鼠标和/或键。当然,你必须捕获所有的鼠标和按键,因为点击任何小部件都会让你失去焦点。这没有帮助,因为当按下TAB时,KeyListener什么都不做。。。如果KeyListener使用TAB,我根本不会问这个问题……:)PS,我明白你的意思,但是如果我不能用TAB键检测到焦点丢失,跟踪鼠标事件是没有用的。如果我可以得到TAB键,我根本不需要鼠标事件(其余的都是鼠标事件,因为它们是唯一没有被覆盖的)。见编辑2。感谢克利奥帕特拉,终于有人理解了这个问题。。。当我的组合框处于表单(不是单元格编辑器)中时,我不会提交任何内容。这是全自动的。您可能知道,导航时会自动调用setSelectedItem()。所以,我要做的是——当用户按下ENTER键或使用鼠标拾取一个项目时,我将其存储起来,这样我就知道实际拾取的是什么项目。(这等于未提交,因为我始终显示最近拾取的项目)。我无法将其设置为相信它是一个单元编辑器,因为当它是一个单元编辑器时,我有单独的逻辑…:(如果你看一下我的编辑2,你会看到我现在正在尝试做什么…这似乎是最简单的解决方案。你怎么想?可能不明白你在追求什么;-)设置客户端属性会使组合按照你描述的要求运行,IMO:用户可以导航而无需提交(又名:选择组合)在下拉列表中选择的项目。如果他/她想要提交,他/她必须主动提交-按ENTER键或通过鼠标单击下拉列表。如果我的组合框是单元格编辑器时没有单独的逻辑,或者不是单元格编辑器时没有单独的逻辑,那么
JTable.isCellEditor
client属性将完全满足我的要求。但不幸的是,这将打破我的逻辑,以防它不是单元格编辑器…:(所以我要么重构它,要么禁用焦点遍历和捕获选项卡…重构-因为对我来说,听起来你走错了方向,疯狂猜测,当然,没有看到任何细节:-)用sscce来准确描述你需要什么,以及为什么你认为你不能使用上述方法,怎么样?
    final JComboBox simpleBox = new JComboBox(Locale.getAvailableLocales());
    // this line configures the combo to only commit on ENTER 
    // or selecting an item from the list
    simpleBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
    //
    // simpleBox.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
    //     Collections.EMPTY_SET);
    // just noticed the OPs edit - following indeed is easier to disable _all_ traversal
    // keys with one statement
    simpleBox.setFocusTraversalKeysEnabled(false);

    Action myAction = new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            LOG.info("got it!");
            simpleBox.transferFocus();
        }

    };
    simpleBox.getActionMap().put("tab-action", myAction);
    simpleBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
       .put(KeyStroke.getKeyStroke("TAB"), "tab-action");