>情况
假设您有一个包含单个复杂控件的Scene
,该控件本身包含一个TextArea
。复杂控件的组成方式是,当它获得焦点时,TextArea
获得焦点。
ComplexControl 能够使 TextArea 不可编辑。然后,键输入可以具有比操作文本不同的语义。新的语义可以由 ComplexControl 或场景图中更高的任何节点来定义。
场景具有全局快捷键 CTRL+N,用于打开新的选项卡/视图。在 ComplexControl 的上下文中,CRTL+N 语义正在创建一个新的文本文档。
------------------------
| Scene |
| ------------------ |
| | ComplexControl | |
| | ------------ | |
| | | TextArea | | |
| | ------------ | |
| ------------------ |
------------------------
目的
全局反应或由场景图中稍高的节点做出反应 键事件/键组合。任何稍低的控件都可以接管事件,因此在更特殊的上下文中,发生的事件与全局定义的相关性更高。
建议
在Scene
或更高的Node
上设置KeyHandler
。任何靠近EventDispatchChain
的源/目标的EventHandler
都可以使用事件。这样,KeyHandler
可以防止Scene
或任何更高的Node
对键输入做出反应,这是用户在控件的特殊上下文中的意图。因此,在较高的地方EventFilter
是不合适的。
麻烦
TextArea
始终使用任何关键事件,即使这不是设计的意图。EventDispatchChain
中没有更高的EventHandler
被告知。
问题
- 怎么能强迫它从
TextArea
中归还事件而不消耗它,然后让它冒出EventDispatchChain
? - 如何在不使用它的情况下阻止将事件传递到文本区域,使其甚至不知道有关事件的任何信息。
感谢傻蝇,他为我指明了道路。作为问题 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 的答案,请随时加入。