JavaFX KeyEvent 传播顺序

2023-12-26

我想听场景中的一些 KeyEvent,比如KeyCode.ESCAPE(按下时关闭场景)。

scene.addEventHandler(KeyEvent.ANY, event -> {
            if (event.isConsumed())
                return;
            switch (event.getCode()) {
            case ESCAPE:
                stage.hide();
                event.consume();
                break;
            default:
                break;
            }
        });

现在,场景内的节点可以监听ESCAPE too.

// ....
someOtherNode.addEventHandler(KeyEvent.ANY, e -> {
        if (e.getCode() == KeyCode.ESCAPE) {
            // do stuff
            e.consume();
        }
});
// ....

我如何确保KeyEvent将从节点而不是场景消耗?

根据 Oracle 的图表,解决方法是添加一个虚拟Node在监听的 Node 层次结构的末尾KeyCodes

但有没有更好的解决方案,比如反转传播路径?

EDIT:

使用案例:

阻止其他节点的类似弹出窗口的节点需要侦听 ESC 键或focusProperty()以便它可以自行关闭。


您可以通过两种方式影响事件:

  1. Use the Node.addEventFilter(...) http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#addEventFilter%28javafx.event.EventType,%20javafx.event.EventHandler%29注册过滤器的方法。过滤器将在事件的捕获阶段执行(随着窗口变得更加具体,确定哪些节点应该获取事件)。

  2. Use the Node.addEventHandler(...) http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#addEventHandler%28javafx.event.EventType,%20javafx.event.EventHandler%29方法来注册处理程序。处理程序将从捕获阶段找到的最具体的节点开始执行,一直向下直到被消耗。

所以在捕获阶段,会创建一个堆栈。从窗口(最上面的父级)开始,该事件可能执行的每个节点都被添加到堆栈中(以最下面的子级结束)。过滤器可以中断此过程,或者仅在此过程中执行事件。

在冒泡阶段,事件处理程序将从堆栈顶部(在捕获阶段创建)开始触发,直到堆栈为空或事件被消耗。

就您的情况而言,您确实不必担心。如果任何节点关心处理“ESC”事件,它们将在冒泡阶段执行此操作(并且它们应该消耗该事件以防止进一步处理)。您可以在ComboBox。如果他们不在乎,它就会冒泡到你的Scene该处理程序将执行。只需确保您创建的任何处理“ESC”按下的自定义代码也消耗该事件。

有关更多信息,这里有解释和教程:http://docs.oracle.com/javafx/2/events/jfxpub-events.htm http://docs.oracle.com/javafx/2/events/jfxpub-events.htm

这是一些演示 Escape 功能的示例代码。聚焦时按 ESCComboBox不会导致应用程序关闭,但会与其他控件一起关闭。

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.converter.DefaultStringConverter;


public class FXEventFiltering extends Application {

    public static void main(String[] args) { launch(args); }

    @Override
    public void start(final Stage stage) throws Exception {
        //All the controls are added here
        VBox box = new VBox();
        ComboBox<String> dropdown = new ComboBox<>();
        TextField field = new TextField();
        CheckBox check = new CheckBox("Check");
        RadioButton radio = new RadioButton("Radio!");
        TextArea area = new TextArea();
        TableView<String> table = new TableView<String>(FXCollections.observableArrayList(new String[]{"one","two"}));
        TableColumn<String, String> tc = new TableColumn<String, String>("Column1");
        tc.setEditable(true);
        tc.setCellFactory(TextFieldTableCell.<String,String>forTableColumn(new DefaultStringConverter()));
        tc.setCellValueFactory(new Callback<CellDataFeatures<String,String>, ObservableValue<String>>(){
            @Override
            public ObservableValue<String> call(CellDataFeatures<String, String> arg0) {
                return new SimpleStringProperty(arg0.getValue());
            }});
        table.getColumns().add(tc);

        box.getChildren().addAll(dropdown, field, check, radio, area, table);

        //Setting up your scene
        Scene scene = new Scene(box);
        stage.setScene(scene);
        scene.addEventHandler(KeyEvent.ANY, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                System.out.println("KEYS!" + event.getEventType().getName());
                switch (event.getCode()) {
                case ESCAPE:
                    System.out.println("Escape!");
                    stage.hide();
                    event.consume();
                    break;
                default:
                    break;
                }
            }
        });

        box.requestFocus(); // Removing default focus

        stage.show();
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaFX KeyEvent 传播顺序 的相关文章

随机推荐