javaeventsjavafxeventhandlereventfilter

Javafx one eventhandler to catch them all?


I am playing around with javafx and am trying to add an EventHandler or EventFilter (not totally sure what the difference is right now) to one of my scenes. It should just detect any input, from mouse clicks to keys pressed.

I was able to write an EventFilter for mouse clicks but I cannot get it to work for any event in general.

My current idea was the following:

        scene.addEventFilter(Event.ANY, new EventHandler<InputEvent>() {
            @Override
            public void handle(InputEvent event) {
                System.out.println("Event detected! " + event.getSource());
            }
        });

But with this I get addEventFilter highlighted red with an error message like this:

The method addEventFilter(EventType<T>, EventHandler<? super T>) in the type Scene is not applicable for the arguments (EventType<Event>, new EventHandler<InputEvent>(){})

I am new to Java and I don't understand what to do. I wanted to catch input events within my scene but without the need of having a separate filter for every possible event.


Solution

  • The method signature, as shown in the error message, is

    addEventFilter(EventType<T>, EventHandler<? super T>) 
    

    Since Event.ANY is an EventType<Event>, you need an EventHandler<T> where T is either Event or a superclass of Event. I.e.

    scene.addEventFilter(Event.ANY, new EventHandler<Event>() {
        @Override
        public void handle(Event event) {
            System.out.println("Event detected! " + event.getSource());
        }
    });
    

    Alternatively, if you specifically only want to capture InputEvents, note that InputEvent.ANY is an EventType<InputEvent>, so in that case you could do

    scene.addEventFilter(InputEvent.ANY, new EventHandler<InputEvent>() {
        @Override
        public void handle(InputEvent event) {
            System.out.println("Event detected! " + event.getSource());
        }
    });
    

    In more modern syntax, these are just

    scene.addEventFilter(InputEvent.ANY,  
            event -> System.out.println("Event detected! " + event.getSource())
    );
    

    (or the same, replacing InputEvent.ANY with Event.ANY).

    Note that in this latter version, all the types are automatically inferred, so you essentially sidestep the possibility of making that error.