2012-02-12 82 views
2

我想了解如何检测JComboBox是否在用户按下Tab或通过在组件区域外单击鼠标时失去焦点。如何检测JComboBox中的TAB按键?

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

编辑1: 我想实现的是:

  • 假设用户下拉列表(JComboBox中弹出菜单显示出来),并通过光标键导航...
  • 案例1:用户按下标签。在这种情况下,我想切断项目中的一些信息,只显示一些部分。第二种情况:用户在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 

感谢所有与会者的讨论!

+0

*“任何想法,将不胜感激。” *解释用例的这个功能。您想通过了解哪些功能为最终用户提供? – 2012-02-12 15:01:53

+0

安德鲁,感谢您的回复,请参阅*编辑1 *。 – DejanLekic 2012-02-12 15:15:52

回答

5

当我明白你的问题,有两个独立的问题

  • 在导航的同时
  • 接管反应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"); 
+0

感谢Kleopatra,终于明白这个问题的人......当我的组合框处于一种形式(而不是单元编辑器)时,我什么都不做。这全是自动的。正如您可能知道的那样,在您导航时,会自动调用setSelectedItem()。所以,我所做的是 - 当用户按下ENTER时,或使用鼠标选择一个项目时,我存储该项目,所以我知道哪些项目实际选中。 (这等于不提交,因为我总是显示最新的PICKED项目)。我不能确定它是一个单元格编辑器,因为当它是一个单元格编辑器时,我有单独的逻辑...... :( – DejanLekic 2012-02-12 15:55:16

+0

如果你看看我的*编辑2 *,你会看到我我想现在就做...这似乎是最简单的解决方案,你在想什么 – DejanLekic 2012-02-12 16:01:02

+0

可能不知道你在做什么之后;-)设置客户端属性会使组合表现得像你描述你的需求,IMO:用户可以浏览没有提交(又名:选择组合)在下拉列表中选择的项目。如果他/她想提交,他/她已经这么做了 - 无论是按ENTER还是通过鼠标点击进入下拉菜单。没有其他代码可用于“点击”情况 – kleopatra 2012-02-12 16:10:01

3

假设您在松开焦点之前已按下鼠标(或键)。因此,倾听所有的键盘和鼠标点击,并且在丢失焦点之前使用的那个是罪魁祸首。

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

+0

FocusLost无论如何都被解雇了,当用户按TAB时,或者当用户点击某处时,我找不到它是否被解雇......这是问题的实质。 – DejanLekic 2012-02-12 15:15:24

+0

是的,所以当focuslost被触发时,你会检查你在窗口的任何部分按下鼠标或键时设置的变量。这个变量只记录最后一个鼠标和/或键被按下。你当然必须捕获所有的鼠标和按键,因为点击任何小部件都会让你失去焦点。 – 2012-02-12 15:19:58

+0

这没有帮助,因为按Tab键时,KeyListener什么也不做......如果KeyListener与TAB一起工作,我根本不会问这个问题...... :) – DejanLekic 2012-02-12 15:38:11