1 Processing Events
This topic describes events and the handling of events in JavaFX applications. Learn about event types, event targets, event capturing, event bubbling, and the underlying architecture of the event processing system.
Events are used to notify your application of actions taken by the user and enable the application to respond to the event. The JavaFX platform provides the structure for capturing an event, routing the event to its target, and enabling the application to handle the event as needed.
An event represents an occurrence of something of interest to the application, such as a mouse being moved or a key being pressed. In JavaFX, an event is an instance of the
javafx.event.Event class or any subclass of
Event. JavaFX provides several events, including
ScrollEvent, and others. You can define your own event by extending the
Every event includes the information described in Table 1-1.
Table 1-1 Event Properties
Type of event that occurred.
Origin of the event, with respect to the location of the event in the event dispatch chain. The source changes as the event is passed along the chain.
Node on which the action occurred and the end node in the event dispatch chain. The target does not change, however if an event filter consumes the event during the event capturing phase, the target will not receive the event.
Event subclasses provide additional information that is specific to the type of event. For example, the
MouseEvent class includes information such as which button was pushed, the number of times the button was pushed, and the position of the mouse.
An event type is an instance of the
EventType class. Event types further classify the events of a single event class. For example, the
KeyEvent class contains the following event types:
Event types are hierarchical. Every event type has a name and a super type. For example, the name of the event for a key being pressed is
KEY_PRESSED, and the super type is
KeyEvent.ANY. The super type of the top-level event type is null. Figure 1-1 shows a subset of the hierarchy.
Figure 1-1 Event Type Hierarchy
Description of "Figure 1-1 Event Type Hierarchy"
The top-level event type in the hierarchy is
Event.ROOT, which is equivalent to
Event.ANY. In the subtypes, the event type
ANY is used to mean any event type in the event class. For example, to provide the same response to any type of key event, use
KeyEvent.ANY as the event type for the event filter or event handler. To respond only when a key is released, use the
KeyEvent.KEY_RELEASED event type for the filter or handler.
The target of an event can be an instance of any class that implements the
EventTarget interface. The implementation of the
buildEventDispatchChain creates the event dispatch chain that the event must travel to reach the target.
Node classes implement the
EventTarget interface and subclasses of those classes inherit the implementation. Therefore, most of the elements in your user interface have their dispatch chain defined, enabling you to focus on responding to the events and not be concerned with creating the event dispatch chain.
If you create a custom UI control that responds to user actions and that control is a subclass of
Node, your control is an event target through inheritance. If your control or an element of your control is not a subclass of
Node, you must implement the
EventTarget interface for that control or element. For example, the
MenuBar control is a target through inheritance, but the
MenuItem element of a menu bar must implement the
EventTarget interface so that it can receive events.
Event Delivery Process
The event delivery process contains the following steps:
When an action occurs, the system determines which node is the target based on internal rules:
For key events, the target is the node that has focus.
For mouse events, the target is the node at the location of the cursor. For synthesized mouse events, the touch point is considered the location of the cursor.
For continuous gesture events that are generated by a gesture on a touch screen, the target is the node at the center point of all touches at the beginning of the gesture. For indirect gesture events that are generated by a gesture on something other than a touch screen, such as a trackpad, the target is the node at the location of the cursor.
For swipe events that are generated by a swipe on a touch screen, the target is the node at the center of the entire path of all of the fingers. For indirect swipe events, the target is the node at the location of the cursor.
For touch events, the default target for each touch point is the node at the location first pressed. A different target can be specified using the
)methods for a touch point in an event filter or event handler.
If more than one node is located at the cursor or touch, the topmost node is considered the target. For example, if a user clicks or touches the triangle shown in Figure 1-2, the triangle is the target, not the rectangle that contains the circle and the triangle.
Figure 1-2 Sample User Interface Event Targets
Description of "Figure 1-2 Sample User Interface Event Targets"
When a mouse button is pressed and the target is selected, all subsequent mouse events are delivered to the same target until the button is released. Similarly for gesture events, from the start of the gesture to the completion of the gesture, gesture events are delivered to the target identified at the beginning of the gesture. The default for touch events is to deliver the events to the initial target node that was identified for each touch point, unless the target is modified using the
The initial event route is determined by the event dispatch chain that was created in the implementation of the
buildEventDispatchChain() method of the selected event target. For example, if a user clicks the triangle shown in Figure 1-2, the initial route is shown by the gray nodes in Figure 1-3. When a scene graph node is selected as an event target, the initial event route set in the default implementation of the
buildEventDispatchChain() method in the
Node class is a path from the stage to itself.
Figure 1-3 Event Dispatch Chain
Description of "Figure 1-3 Event Dispatch Chain"
The route can be modified as event filters and event handlers along the route process the event. Also, if an event filter or event handler consumes the event at any point, some nodes on the initial route might not receive the event.
Event Capturing Phase
In the event capturing phase, the event is dispatched by the root node of your application and passed down the event dispatch chain to the target node. Using the event dispatch chain shown in Figure 1-3, the event travels from the Stage node to the Triangle node during the event capturing phase.
If any node in the chain has an event filter registered for the type of event that occurred, that filter is called. When the filter completes, the event is passed to the next node down the chain. If a filter is not registered for a node, the event is passed to the next node down the chain. If no filter consumes the event, the event target eventually receives and processes the event.
Event Bubbling Phase
After the event target is reached and all registered filters have processed the event, the event returns along the dispatch chain from the target to the root node. Using the event dispatch chain shown in Figure 1-3, the event travels from the Triangle node to the Stage node during the event bubbling phase.
If any node in the chain has a handler registered for the type of event encountered, that handler is called. When the handler completes, the event is returned to the next node up the chain. If a handler is not registered for a node, the event is returned to the next node up the chain. If no handler consumes the event, the root node eventually receives the event and processing is completed.
Event handling is provided by event filters and event handlers, which are implementations of the
EventHandler interface. If you want an application to be notified when an event occurs, register a filter or a handler for the event. The primary difference between a filter and a handler is when each one is executed.
An event filter is executed during the event capturing phase. An event filter for a parent node can provide common event processing for multiple child nodes and if desired, consume the event to prevent the child node from receiving the event. Filters that are registered for the type of event that occurred are executed as the event passes through the node that registered the filter.
A node can register more than one filter. The order in which each filter is called is based on the hierarchy of event types. Filters for a specific event type are executed before filters for generic event types. For example, a filter for the
MouseEvent.MOUSE_PRESSED event is called before the filter for the
InputEvent.ANY event. The order in which two filters at the same level are executed is not specified.
An event handler is executed during the event bubbling phase. If an event handler for a child node does not consume the event, an event handler for a parent node can act on the event after a child node processes it and can provide common event processing for multiple child nodes. Handlers that are registered for the type of event that occurred are executed as the event returns through the node that registered the handler.
A node can register more than one handler. The order in which each handler is called is based on the hierarchy of event types. Handlers for a specific event type are executed before handlers for generic event types. For example, a handler for the
KeyEvent.KEY_TYPED event is called before the handler for the
InputEvent.ANY event. The order in which two handlers at the same level are executed is not specified, with the exception that handlers that are registered by the convenience methods described in Working with Convenience Methods are executed last.
Consuming of an Event
An event can be consumed by an event filter or an event handler at any point in the event dispatch chain by calling the
consume() method. This method signals that processing of the event is complete and traversal of the event dispatch chain ends.
Consuming the event in an event filter prevents any child node on the event dispatch chain from acting on the event. Consuming the event in an event handler stops any further processing of the event by parent handlers on the event dispatch chain. However, if the node that consumes the event has more than one filter or handler registered for the event, the peer filters or handlers are still executed.
For example, using the event dispatch chain shown in Figure 1-3, assume that the Pane node has an event filter registered for the
KeyEvent.KEY_PRESSED event and an event filter registered for the
InputEvent.ANY event. If the filter for the key pressed event consumes the event, the filter for the input event is executed and the Triangle node does not receive the event.
Note that the default handlers for the JavaFX UI controls typically consume most of the input events.
For more information on how events are processed, see the JavaFX API documentation for the