如何在JComboBox中检测TAB按键?

时间:2012-02-12 14:54:53

标签: java swing jcombobox key-bindings

我试图找出如何在用户按下标签或通过鼠标点击组件区域外时检测JComboBox是否失去焦点。

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

编辑1: 我想要实现的是:

  • 假设用户下拉列表(JComboBox popupMenu显示),并通过光标键导航...
  • 案例1:用户按Tab键。在这种情况下,我想从项目中删除一些信息,只显示一些部分。
  • 案例2:用户在popupMenu区域外点击鼠标(这里我们有子句,但它们都属于同一类别)。在这种情况下,我想更改JComboBox以显示以前编辑的项目,而不是用户导航的内容......
  • 还有其他几种情况(鼠标项目选择,回车键,转义等)。我可以轻松处理这些,但检测选项卡很棘手,因为我无法捕获此事件,因为它由FocusManager处理。

编辑2: 似乎我必须使用setFocusTraversalKeysEnabled(false)在按下TAB时收到通知,当我捕获该事件时,我应该手动转移焦点...我不喜欢这个解决方案,但这是迄今为止最好的我可以想出来。

解决方案:

以下一段Java代码实际上解决了我的问题。正如我在 Edit 2 中所写,最简单的解决方案是禁用焦点遍历。我无耻地借用了Kleopatra的代码,现在一切正常。 :)

    if (!isTableCellEditor()) {
        comboBoxEditor.setFocusTraversalKeysEnabled(false);

        Action myAction = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                handleTabPress();
                comboBoxEditor.transferFocus();
            } // actionPerformed() method
        };

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

感谢所有与会者参与讨论!

2 个答案:

答案 0 :(得分:6)

据我了解你的问题,有两个不同的问题

  • 导航时不提交值
  • 接管对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");

答案 1 :(得分:3)

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

当触发focuslost时,您将检查在窗口的任何部分按下鼠标或键时设置的变量。此变量仅记录最后按下的鼠标和/或键。当然,您必须捕获所有鼠标和按键,因为单击任何小部件都会让您失去焦点。