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

发布于 2025-01-05 03:41:00 字数 1343 浏览 3 评论 0原文

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

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

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

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

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

解决方案:

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

    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

感谢所有参与讨论的人!

I am trying to find out how to detect if a JComboBox lost focus when user pressed tab or via a mouse-click outside the component's area.

Adding a FocusListener to the editor component of the JComboBox does not help me, as I can't find out if user used the mouse or moved the focus via the tab key. Any ideas would be greatly appreciated.

Edit 1:
What I am trying to achieve is this:

  • Suppose user drops down the list (JComboBox popupMenu shows up), and navigates via cursor keys...
  • Case 1: user presses tab. In this case, I want to cut off some of the information from the item and show only some parts.
  • Case 2: user clicks with the mouse outside the popupMenu's area (here we have subcases, but they all fall into the same category). In this case I want to change JComboBox to show the previously edited item, not what user navigated...
  • There are several other cases (mouse item pick, the enter key, escape, etc.). I could easily handle these, but detecting tab is tricky because I can't catch this event as it is handled by FocusManager.

Edit 2:
It seems that I have to use setFocusTraversalKeysEnabled(false) to get notified when TAB is pressed, and when i capture that event, I should manually transfer focus... I do not like this solution, but that is so far the best I could come up with.

Solution:

Following piece of Java code is actually solving my problem. As I wrote in Edit 2 the easiest solution was to disable focus traversal. I shamelessly borrowed Kleopatra's code, and all works now. :)

    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

Thanks to all participants in the discussion!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尤怨 2025-01-12 03:41:00

据我了解你的问题,有两个单独的问题,

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

As I understand your question, there are two separate problems

  • don't commit the value while navigating
  • take over the reaction to TAB

if so, the answers are

  • configure the combo so that it thinks it is the editing component of a CellEditor
  • disable the default traversal keys for the combo and take over with a custom binding

In code:

    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");
少女的英雄梦 2025-01-12 03:41:00

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

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

It is assumed that you have pressed the mouse (or key) right before you loose focus. So listen to all the keyboard and mouse clicks, and the one used last right before loosing focus is the culprit.

When focuslost is fired, you would check a variable you set when a mouse or key is pressed, on any part of your window. This variable just logs the last mouse and/or key pressed. You would have to capture all the mouse and keypresses of course, since clicking on any widget would let you loose focus.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文