禁止子节点被告知事件而不消耗相同的事件

时间:2018-01-30 12:56:06

标签: user-interface javafx event-handling

场合

假设您有一个Scene,其中包含一个复杂的控件,它本身包含TextArea。复合控制以某种方式组成,当它获得焦点时,TextArea获得焦点。

ComplexControl能够使TextArea不可编辑。然后,键输入可以具有除操作文本之外的另一种语义。新的语义可以由ComplexControl或任何节点定义,在场景图中更高。

场景具有全局快捷键CTRL + N,用于打开新的选项卡/视图。在ComplexControl的上下文中,CRTL + N语义正在创建一个新的文本文档。

------------------------
| Scene                |
|  ------------------  |
|  | ComplexControl |  |
|  |  ------------  |  |
|  |  | TextArea |  |  |
|  |  ------------  |  |
|  ------------------  |
------------------------

目标

在KeyEvents / KeyCombinations的场景图中全局或由某个节点稍微反应。任何较低的控制都可以接管事件,因此在更特殊的上下文中,发生的事件与全局定义具有更多相关性。

建议

KeyHandler设置为Scene或更高Node。靠近EventHandler的来源/目标的任何EventDispatchChain都可以使用此事件。KeyHandler可以阻止Scene或任何更高的Node对键输入作出反应,这是用户在控件的特殊上下文中的意图。因此,较高位置的EventFilter不合适。

故障

TextArea总是消耗任何关键事件,即使这不是设计的意图。 <{1}}中的EventHandler更高通知。

问题

  1. 如何强制从EventDispatchChain发回事件而不消耗它,然后让它冒出TextArea
  2. 如何在不消费的情况下阻止将事件传递到TextArea,以便它甚至不知道有关该事件的任何信息。

1 个答案:

答案 0 :(得分:1)

Thanx到sillyfly,谁给我指路。作为对问题2的回答,这里是结果来源。我决定将功能放在中心点以便重用,并提供基于抑制条件的机会。请不要责怪我的班级名称,这不是重点; - )

public class EventUtil {

  /**
   * Prevents Events of the given <b>eventTypes</b> to be passed down during the
   * event capturing phase, if the <b>condition</b> is met.
   * 
   * @param node
   *          The Node, whose descendants should not be informed about the Event
   * @param eventTypes
   *          The types of Events for which the prevention should be valid
   * @param condition
   *          The condition that must be met to prevent passing the Event down
   */
  public static void preventPassDown(Node node, Supplier<Boolean> condition, EventType<?>... eventTypes) {
    for (EventType<?> eventType : eventTypes) {
      if (eventTypes == null) {
        return;
      }
      node.addEventFilter(eventType, event -> {
        if (condition.get()) {
          event.consume();
          Parent parent = node.getParent();
          if (parent != null) {
            Event.fireEvent(parent, event);
          }
        }
      });
    }
  }

  /**
   * Prevents Events of the given <b>eventTypes</b> to be passed down during the
   * event capturing phase.
   * 
   * @param node
   *          The Node, whose descendants should not be informed about the Event
   * @param eventTypes
   *          The types of Events for which the prevention should be valid
   */
  public static void preventPassDown(Node node, EventType<?>... eventTypes) {
    preventPassDown(node, () -> true, eventTypes);
  }

如果有人找到问题1的答案,请随时加入。