Stop file chooser key event propagation to the (parent) stage in JavaFX

Viewed 177

I need to listen to key events in stage but not when the FileChooser is displayed.

Is there a way to stop KeyEvent (e.g. Esc key is pressed.) propagation to (parent) Stage, when FileChooser is displayed?

OR

Detect that the KeyEvent is propagated from FileChooser?

class KeyEventTest extends Application
{
  @Override
  public void start(Stage stage) throws Exception
  {
    Button browseBtn = new Button("Browse File System");
    browseBtn.setOnAction(ae ->
      {
        FileChooser fileChooser = new FileChooser();
        fileChooser.showOpenMultipleDialog(stage);
      });

    stage.setScene(new Scene(new BorderPane(browseBtn), 500, 200));
    stage.setTitle("Test");

    stage.addEventHandler(KeyEvent.KEY_RELEASED, keyEvent ->
      {
        // Do not trigger when Esc key is pressed on FileChooser
        KeyCode keyCode = keyEvent.getCode();
        System.out.println(keyCode);
      });

    stage.centerOnScreen();
    stage.show();
  }

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

It is possible to achieve it. You are correct that if you close the FileChooser using either escape or ALT+F4 the event will be propagated, but you need to think which event will? if you have a look only the KeyEvent.KEY_RELEASED will. So if you just add an event filter recording when the key was pressed you can find out when you pressed the escape ( or alt+f4 ) in your main stage or in your FileChooser

So more or less you are trying to find out if the KEY_PRESSED was handled by FileChooser or not. If it was, then the KEY_RELEASED will also be handled from FileChooser otherwise we trigger the KeyEvent in our main app.

Here is an example :

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class Main extends Application {

    private boolean captureKeys = false;

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

    @Override
    public void start(Stage stage) {
        Button browseBtn = new Button("Browse File System");
        browseBtn.setOnAction(ae -> {
            captureKeys = false;
            FileChooser fileChooser = new FileChooser();
            fileChooser.showOpenMultipleDialog(stage);
        });

        stage.setScene(new Scene(new BorderPane(browseBtn), 500, 200));

        stage.addEventFilter(KeyEvent.KEY_PRESSED, keyEvent -> {
            captureKeys = true;
            // For debug
            // KeyCode keyCode = keyEvent.getCode();
            // System.out.println("KEY_PRESSED on Stage : " + keyCode);
        });

        stage.addEventHandler(KeyEvent.KEY_RELEASED, keyEvent -> {
            if(captureKeys) {
                KeyCode keyCode = keyEvent.getCode();
                System.out.println(keyCode);
            }
        });

        stage.centerOnScreen();
        stage.show();
    }
}
Related