在Java中,e.consume()是什么意思?

15

我在网上搜索,没有找到关于在Java KeyEvent处理中经常使用的e.consume()的清晰解释。就像下面的代码一样。

public void keyTyped( KeyEvent e ) {
    char c = e.getKeyChar();
    if ( c != KeyEvent.CHAR_UNDEFINED ) {
        s = s + c; 
        repaint();
        e.consume();
    } 
}
5个回答

9

来自JavaDocs

消耗此事件,以使其不会被源默认方式处理。

本质上,这意味着如果您不希望事件被分派或由任何其他事件侦听器处理。

尽管通常情况下,这取决于各个侦听器的实现。


1
在 JTextField 上,如果键入事件被消耗,则字符不会添加到字段中。但是其他声明的侦听器仍然被调用,它们可以检查 event.isConsumed() 来决定是否应处理该事件。请注意,侦听器实际上按照它们声明的顺序被调用。 - Emmanuel Bourg
1
根据我的经验,监听器是按照LIFO顺序调用的 - 因此最后添加的监听器理论上可以消费事件。实际上,事件消费的处理方式因各个分发器的实现而异 :/ - MadProgrammer
java.awt.Component 只有一个键监听器,addKeyListener 调用 AWTEventMulticaster.add(currentListener, addedListener) 添加新的监听器。创建的组合监听器先调用旧的监听器,再调用新增加的监听器,因此监听器按照注册的顺序通知。 - Emmanuel Bourg
恭喜您,您正在谈论一种核心监听器,我在2012年时通常讨论的是那些利用“EventListenerList”的监听器,该监听器以相反的顺序排列监听器。很抱歉我的表述不够清晰。 - MadProgrammer
没错,输入事件(键盘事件、鼠标事件,拖动事件除外)的监听器按照正常顺序通知,但所有其他事件(操作事件、更改事件、表格模型事件等)则按相反顺序通知。EventListenerList 实际上并不以相反顺序存储侦听器,组件只是以相反顺序遍历列表。 - Emmanuel Bourg
1
再次强调,我并没有说EventListenerList以相反的顺序“存储”它们,我只是说它以相反的顺序“排序”它们——内部机制应该在很大程度上是实现细节,对于调用者来说,重要的是它看起来是什么样子。在我的回答中,我从未提到“内部”机制或KeyEventKeyListener,而是做了一个“抽象”的观察。因为,正如我们所看到的,在API中有多个事件分派工作流程。 - MadProgrammer

4
看一下文档:KeyEvent从InputEvent类继承了consume方法。consume方法会消费此事件,使得它不会被产生该事件的源默认处理

3

Consume函数负责在发生特定类型事件时不处理KeyListeners代码。例如:如果我想创建一个Java中的textfield,使其只在按数字键时响应,那么我可以使用consume方法来消费(不处理由于未按数字键而引起的按键事件)此类事件。


请注意,消耗按键事件并不会阻止 JTextField 被更新,您需要消耗按键类型事件。 - Emmanuel Bourg

2
这是AWTEvent类的一个方法。如果该事件可以被消费,它会被用来消费此事件。
你是否查看了AWTEvent.consume()?
此外,查看How Does consume() Work?以了解consume实际上是如何工作的。

消费是否意味着结束此事件? - user1456170
不。这意味着该事件将不会被进一步分派到任何其他事件侦听器。 - Kazekage Gaara
似乎我被一个简单的词卡住了,现在我明白了。感谢任何人的回复,特别是你的。 - user1456170
AWTEvent.consume()是受保护的... 完全没用。 - miXo
@KazekageGaara 即使事件已被消耗,它仍然会被分派到其他侦听器,他们必须检查 event.isConsumed() 是否要跳过它。 - Emmanuel Bourg

0

当事件被消耗时,事件源(例如在键入按键时具有焦点的JTextField)将忽略该事件。

如果您查看JComponent类的processKeyEvent方法:

protected void processKeyEvent(KeyEvent e) {
    boolean result;
    boolean shouldProcessKey;

    // This gives the key event listeners a crack at the event
    super.processKeyEvent(e);

    // give the component itself a crack at the event
    if (! e.isConsumed()) {
        processComponentKeyEvent(e);
    }

你可以看到首先调用了super.processKeyEvent(e),这将事件分派给使用component.addKeyListener()注册的侦听器。侦听器按照它们最初注册的顺序通知,并且即使其中一个侦听器消耗了事件,它们也会全部被通知。唯一可以阻止剩余侦听器处理事件的是未捕获的异常。

在通知完侦听器后,组件本身将处理事件,但仅当事件尚未被任何侦听器消耗时才会处理。对于JTextField,如果侦听器消耗了键入事件,则该字段不会更新(但消耗按下事件将没有影响)。

请注意,鼠标事件的行为不同,由侦听器消耗的事件仍然会被组件处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接