Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java FX - different aspects of event handling

I'm trying to get my head around the different aspects to event handling within Java FX. I've read through the Oracle material but I'm still left a little confused and wondered if someone could explain the differences and key uses of some of the different options available in a succinct manner.

Firstly, from what I can see there are Event Handlers and Event Filters and then there are convenience methods. So what's the key difference between Handlers and Filters and why I would use one over another. Furthermore, what are the benefits of adding an Event Handler using addEventHandler(...) rather than using the convenience method? From my own testing I believe using addEventHandler(...) you can attach multiple event handlers to a given control, whereas using setOnEvent-type(...) only allows one event handler to be attached, as it overwrites the property each time it is set. Any other differences?

There's then the topics of ChangeListener and InvalidationListener - am I correct in thinking that a ChangeListener is a type of event handler, that's specifically designed at listening for change events (of properties)? I cannot seem to find many examples of using a ChangeListener apart from the Oracle page on JavaFX Properties and Binding - does anyone know of a good guide? Furthermore, in simple terms, when would I choose between a ChangeListener and InvalidationListener?

Finally, is it possible to sometimes simulate the same event handling procedure through either a traditional EventHandler or a ChangeListener - e.g. a button click can be handled using the ActionEvent - is there a way to do it through a ChangeListener? I can see that you could theoretically add a change listener to the onActionProperty, but I think this would not be invoked when the button is clicked, but instead if setOnAction actually changed the event handler that was attached?

like image 585
Tranquility Avatar asked Oct 19 '22 15:10

Tranquility


1 Answers

So what's the key difference between Handlers and Filters and why I would use one over another.

The key difference is when each one occurs. Event filters are called during event capturing phase, which occurs before event bubbling phase (where event handlers are called). Hence you can filter (consume) events that you do not want to be handled before handlers are notified. Most of the time you would want to simply use a handler and not worry about filters. However, there are cases where you need to filter events. For example, imagine a game where the mouse handler moves the game character. If user opens an in-game menu, you do not want him to be able to click "through" the menu into the game and move the character while menu is open. One possible approach is to filter those mouse events and consume them before they reach the node on which the handler is registered. You can of course attach the mouse handler to something different and not the entire scene, but it is beyond the point emphasized in the example.

Convenience handlers, as the name implies, are there for convenience. It reduces boilerplate code and allows easy API. According to JavaFX doc, they are called last in the event chain. So if you have only one event type of interest, then these methods should be preferred.

To sum up, use convenience and event handlers in this order, if more control over the event dispatching is required you can also add filters.

Furthermore, in simple terms, when would I choose between a ChangeListener and InvalidationListener?

Change listener is notified when a value has, in fact, changed. In order to identify a change, the value must be recomputed. So when you add such a listener to an observable value, it is no longer lazily evaluated but eagerly.

Invalidation listener is notified when a value is no longer valid. This does not, however, mean that the value has changed. This allows us to fire the invalidation event without actually knowing the value. The value will be evaluated before it is accessed.

So, in simple terms, use ChangeListener if you need to know the new value of the observable object, otherwise use InvalidationListener.

I can see that you could theoretically add a change listener to the onActionProperty, but I think this would not be invoked when the button is clicked, but instead if setOnAction actually changed the event handler that was attached?

Yes, you are right. To handle a button click you will need to use setOnAction(). ChangeListener has nothing to do with event handling.

like image 130
AlmasB Avatar answered Oct 21 '22 06:10

AlmasB