JCombobox禁用项目选择(make readboly)

mor*_*s05 5 java swing selection jcombobox

我想创建一个只读组合框.用户不应该从弹出列表中选择另一个项目.这意味着弹出列表不应该打开或应该为空.

我看到以下解决方案:

  • 设置仅包含一个项目(当前所选项目)的ComboBox模型,因此当用户单击箭头按钮时,将显示一个空列表.

  • 添加一个PopupMenuListenerpopupMenuWillBecomeVisible隐藏菜单.这是有问题的:我们必须combo.hidePopup();从内部打电话SwingUtilities.invokeLater()

空模型方法看起来有点笨重.第二种方法显示弹出列表只有几分之一秒,足够短以至于被注意到.这非常难看.

有第三种解决方案吗?

编辑:已实施的解决方案:

我从splungebob实现了建议的方法,这是我的代码供将来参考:

private void makeComboReadonly() {
  Component editorComponent = box.getEditor().getEditorComponent();
  if (editorComponent instanceof JTextField) {
    ((JTextField) editorComponent).setEditable(false);
  }

  for (Component childComponent : box.getComponents()) {
    if (childComponent instanceof AbstractButton) {
      childComponent.setEnabled(false);
      final MouseListener[] listeners = childComponent.getListeners(MouseListener.class);
      for (MouseListener listener : listeners) {
        childComponent.removeMouseListener(listener);
      }
    }
  }

  final MouseListener[] mouseListeners = box.getListeners(MouseListener.class);
  for (MouseListener listener : mouseListeners) {
    box.removeMouseListener(listener);
  }

  final KeyListener[] keyListeners = box.getListeners(KeyListener.class);
  for (KeyListener keyListener : keyListeners) {
    box.removeKeyListener(keyListener);
  }

  box.setFocusable(false);

  //box.getActionMap().clear(); //no effect
  //box.getInputMap().clear();
}
Run Code Online (Sandbox Code Playgroud)

唯一的问题是Key-Event Alt-Down,即使我删除所有关键监听器并清除动作映射,它也会弹出弹出菜单.我通过使组合不可聚焦来规避这个问题.不理想但足够好( - :

spl*_*bob 7

这实际上是一个关于Swing的一个限制的好问题(并且长期以来一直困扰着我).

当...(等待它)时,需要一个只读组合框...表单当前处于只读模式.请注意,来自用户elswhere的输入可能会在一瞬间将表单翻转为编辑模式,因此切换JComponents(例如使用JLabel)在视觉上是不可取的,IMO.另请注意,禁用的组合不会向用户传达相同的信息,因为只读组合会:

setEnabled(false) - >完全变灰; 组件无法与之交互; 可能显示的任何数据都不相关,无法选择复制/粘贴.

setReadOnly(true)- >组合的文本组件没有变灰(但是箭头是); 组件无法与之交互; 可以显示的任何数据都是相关的并且可以被选择.

这样做的理由是Swing 确实以JTextComponents的形式实现了这个setEditable(boolean).谢谢大家,但我也需要JComboBox,JCheckbox,JRadioButton等.我们不得不为这个缺失的API推出我们自己的版本.

另一个Swing gaffe(IHMO)是不一致的API. JTextComponent.setEditable(boolean)强制执行只读行为,而不JComboBox.setEditable(boolean)执行.

Arrrgh!

所以,问题.你得卷起袖子.对于可编辑的组合:

  • 通过获取组合的编辑器组件combo.getEditor().getEditorComponent().这是一个JTextField.投它,并打电话setEditable(false).这为您提供了组合的文本部分所需的功能和外观.

  • 通过迭代组合的getComponents()来获取组合的箭头组件.这是你能找到的唯一一个AbstractButton.打电话setEnabled(false).这仅用于外观.

  • 找到组合附带的所有默认鼠标监听器(如果您没有自己添加,则应该是所有这些监听器)并从组合和箭头按钮中删除它们.

  • 保留对这些侦听器和箭头按钮的引用,以防您在只读= false时将其切换回.

或类似的东西.你的旅费可能会改变.

Cue kleopatra得到了对SwingX的认可,它可能已经内置了这个功能(我当然不知道,我只是在猜测).

祝好运.