JavaFX HTMLEditor 覆盖默认输入行为
JavaFX HTMLEditor over-ride default typing behaviour
我有一个具有以下对象的 JavaFX HTML编辑器:
HTMLEditor htmlEditor;
WebView webView;
WebEngine webEngine;
HTMLDocumentImpl htmlDocImpl;
我想要的是在用户按下 Ctrl+Z 时覆盖默认的撤消功能。我是编程新手,但我的理解是 HTMLEditor 没有 undo/redo 功能我可以使用(即使 Ctrl+Z 以某种方式撤消我键入的文本)
我在编辑器中有很多操作 HTML 的函数,所以我需要一个自定义撤消函数。实现我自己的第一步是覆盖当你按 Ctrl+Z
时发生的事情
我似乎不知道该怎么做。例如,试图关闭所有输入功能的这段代码没有任何效果:
htmlEditor.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
e.consume();
});
htmlEditor.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
e.consume();
});
htmlEditor.addEventHandler(KeyEvent.KEY_TYPED, e -> {
e.consume();
});
我如何捕捉特定的按键,取消其默认功能,然后调用我自己的功能?
感谢您的帮助
这是一个演示此操作的示例应用程序:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;
public class EventCapture extends Application {
@Override
public void start(final Stage stage) {
HTMLEditor editor = new HTMLEditor();
editor.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.isMetaDown() && KeyCode.Z.equals(event.getCode())) {
event.consume();
System.out.println("consumed event = " + event);
}
});
stage.setScene(new Scene(editor));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
以上代码是在 Mac 上使用 HTMLEditor 测试的,Java 和 JavaFX 16。这拦截了 Mac 上的默认撤消组合键(命令+ Z) 并忽略它,防止它被路由到底层 HTMLEditor 实现(基于 WebView)。这实际上禁用了编辑器的基于键的撤消功能加速器。对于非 Mac PC(例如 Windows PC),您可能需要拦截不同的组合键。
我发现(通过实验)在 Mac 上触发撤消功能的事件是 KEY_PRESSED 事件(而不是 KEY_TYPED 或 KEY_RELEASED 事件), 所以这就是我选择消费的那个。
为了更好地理解这一点,请阅读 Oracle 的(优秀)tutorial on event handling, which I requested they write and they kindly agreed to do so. Especially, review the section on event filters and the event capturing phase。链接的文档将解释事件捕获阶段(应用过滤器时)和事件冒泡阶段(应用处理程序时)之间的区别,这对于理解此问题的解决方案至关重要。
关于事件过滤器的部分是这样描述它们的:
Event filters are typically used on a branch node of the event dispatch chain and are called during the event capturing phase of event handling. Use a filter to perform actions such as overriding an event response or blocking an event from reaching its destination.
这正是您想要的。
稍微跑题:事件调试提示
要显示在捕获阶段发送到节点的所有事件,请写入:
editor.addEventFilter(EventType.ROOT, System.out::println);
要显示在冒泡阶段发送到节点的所有事件,请写入:
editor.addEventHandler(EventType.ROOT, System.out::println);
其他问题的答案
how come if you remove the event.isMetaDown() condition so its just 'z', then run the program and type 'z', the 'z' isn't consumed and still appears in the editor?
因为'z'在KEY_TYPED
事件发生时出现在编辑器中,而过滤器被写入只过滤KEY_PRESSED
事件。
如果您想过滤 'z' 输入,请更改要过滤的事件类型。
如果您只想过滤小写类型的 'z'(而不是大写),则只消耗匹配字符的 KEY_TYPED
个事件。
editor.addEventFilter(KeyEvent.KEY_TYPED, event -> {
if ("z".equals(event.getCharacter())) {
event.consume();
}
});
我有一个具有以下对象的 JavaFX HTML编辑器:
HTMLEditor htmlEditor;
WebView webView;
WebEngine webEngine;
HTMLDocumentImpl htmlDocImpl;
我想要的是在用户按下 Ctrl+Z 时覆盖默认的撤消功能。我是编程新手,但我的理解是 HTMLEditor 没有 undo/redo 功能我可以使用(即使 Ctrl+Z 以某种方式撤消我键入的文本)
我在编辑器中有很多操作 HTML 的函数,所以我需要一个自定义撤消函数。实现我自己的第一步是覆盖当你按 Ctrl+Z
时发生的事情我似乎不知道该怎么做。例如,试图关闭所有输入功能的这段代码没有任何效果:
htmlEditor.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
e.consume();
});
htmlEditor.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
e.consume();
});
htmlEditor.addEventHandler(KeyEvent.KEY_TYPED, e -> {
e.consume();
});
我如何捕捉特定的按键,取消其默认功能,然后调用我自己的功能?
感谢您的帮助
这是一个演示此操作的示例应用程序:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;
public class EventCapture extends Application {
@Override
public void start(final Stage stage) {
HTMLEditor editor = new HTMLEditor();
editor.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.isMetaDown() && KeyCode.Z.equals(event.getCode())) {
event.consume();
System.out.println("consumed event = " + event);
}
});
stage.setScene(new Scene(editor));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
以上代码是在 Mac 上使用 HTMLEditor 测试的,Java 和 JavaFX 16。这拦截了 Mac 上的默认撤消组合键(命令+ Z) 并忽略它,防止它被路由到底层 HTMLEditor 实现(基于 WebView)。这实际上禁用了编辑器的基于键的撤消功能加速器。对于非 Mac PC(例如 Windows PC),您可能需要拦截不同的组合键。
我发现(通过实验)在 Mac 上触发撤消功能的事件是 KEY_PRESSED 事件(而不是 KEY_TYPED 或 KEY_RELEASED 事件), 所以这就是我选择消费的那个。
为了更好地理解这一点,请阅读 Oracle 的(优秀)tutorial on event handling, which I requested they write and they kindly agreed to do so. Especially, review the section on event filters and the event capturing phase。链接的文档将解释事件捕获阶段(应用过滤器时)和事件冒泡阶段(应用处理程序时)之间的区别,这对于理解此问题的解决方案至关重要。
关于事件过滤器的部分是这样描述它们的:
Event filters are typically used on a branch node of the event dispatch chain and are called during the event capturing phase of event handling. Use a filter to perform actions such as overriding an event response or blocking an event from reaching its destination.
这正是您想要的。
稍微跑题:事件调试提示
要显示在捕获阶段发送到节点的所有事件,请写入:
editor.addEventFilter(EventType.ROOT, System.out::println);
要显示在冒泡阶段发送到节点的所有事件,请写入:
editor.addEventHandler(EventType.ROOT, System.out::println);
其他问题的答案
how come if you remove the event.isMetaDown() condition so its just 'z', then run the program and type 'z', the 'z' isn't consumed and still appears in the editor?
因为'z'在KEY_TYPED
事件发生时出现在编辑器中,而过滤器被写入只过滤KEY_PRESSED
事件。
如果您想过滤 'z' 输入,请更改要过滤的事件类型。
如果您只想过滤小写类型的 'z'(而不是大写),则只消耗匹配字符的 KEY_TYPED
个事件。
editor.addEventFilter(KeyEvent.KEY_TYPED, event -> {
if ("z".equals(event.getCharacter())) {
event.consume();
}
});