【问题标题】:JComboBox second KeyListener prevents first to get firedJComboBox 第二个 KeyListener 防止第一个被解雇
【发布时间】:2015-03-12 22:04:01
【问题描述】:

我正在观察以下行为:

向 JComboBox 添加新的 KeyListener 并调用 e.consume() 会阻止 Default KeyListener 触发其事件。

这是我的示例代码:

final JComboBox cb = new JComboBox(fooList);

final KeyListener fooKeyListener = new KeyAdapter(){
  @Override
  public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_DOWN) {
      System.out.println("VK_DOWN fired");
      e.consume();
    }
  }
};

cb.addKeyListener(fooKeyListener);
contentPanel.add(cb);

在此之后,当我按下向下箭头按钮时,我只会输出“VK_DOWN 触发”并且整个滚动/选择机制停止工作。

我希望,负责所有滚动内容的默认 KeyListener 会首先执行,因此 e.consume() 不应该阻止它工作。顺便说一句,调用e.consume()唯一停止滚动机制的方法!即使调用cb.removeKeyListener(cb.getKeyListeners()[0]); 也不会阻止滚动机制的工作(在我看来,这似乎很奇怪!)。

任何帮助表示赞赏!

【问题讨论】:

    标签: java swing jcombobox keylistener


    【解决方案1】:

    我希望,负责所有滚动内容的默认 KeyListener 会首先执行,

    实际上事件触发的顺序并没有定义,你永远不应该假设一个特定的顺序来编码。事实上,当前的默认实现会调用最先添加的最后一个监听器。

    甚至调用 cb.removeKeyListener(cb.getKeyListeners()[0]);不会阻止滚动机制的工作(在我看来,这似乎很奇怪!)。

    Swing 被设计为使用Key Bindings。通过映射到向下键的默认操作启用滚动。您可以通过查看Key Binding Defaults查看所有默认映射

    调用 e.consume() 是停止滚动机制的唯一方法!

    您可以使用以下方法禁用默认的Key Binding 向下箭头:

    InputMap im = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    im.put(KeyStroke.getKeyStroke("DOWN"), "none");
    

    【讨论】:

    • 当我添加两个 KeyListener 时,其中一个在 keyPressed() 上输出“1”,另一个输出“2”,然后它们总是按照它们被添加到的确切顺序被触发组件。我想相信,默认实现会调用最先添加的最后一个侦听器,但这几乎不是我能观察到的。似乎 Key Bindings 机制在 KeyListener 之后且仅在 (e.isConsumed() == false) 时才被调用。
    • @Hans - 嗯,很有趣。我的印象是所有事件都由EventListenerList 类处理,我认为这是将侦听器添加到组件的标准机制。如果您阅读该类中的文档,您将看到事件以相反的顺序处理。我通过将 ActionListeners 和 KeyListeners 添加到 JButton 进行了快速测试。 KeyListeners 以 FIFO 顺序触发(如您所述), ActionListeners 以 LIFO 顺序触发。所以我们有矛盾。故事的寓意是不要依赖秩序。
    猜你喜欢
    • 1970-01-01
    • 2019-11-28
    • 2012-09-26
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    相关资源
    最近更新 更多