JavaFX KeyEvent Distribution Order

I want to listen to some KeyEvent in my scene, say KeyCode.ESCAPE(close the scene when clicked).

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

Now the nodes inside the scene could also listen ESCAPE.

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

How can I make sure it KeyEventwill be consumed from a node, not a scene?

Based on a chart from Oracle, a workaround would be to add a dummy Nodeat the end of the node hierarchy that listens for KeyCodes

enter image description here

But is there a better solution, for example, inverting the propagation route?

EDIT:

Use case:

A node popup that blocks other nodes will need to listen for the ESC key or focusProperty()so that it can close.

+4
2

:

, . ( ), node, , ( ). .

( ) , .

. - node "ESC", ( ). ComboBox. , Scene . , - , , ESC, .

: http://docs.oracle.com/javafx/2/events/jfxpub-events.htm

, Escape. ESC ComboBox , .

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();
    }

}
+6

, , , , node ? node ?

0

Source: https://habr.com/ru/post/1526009/


All Articles