Handling JavaFX Events

Previous
Next

3 Working with Event Filters

This topic describes event filters in JavaFX applications. Learn how event filters can be used to process the events generated by keyboard actions, mouse actions, scroll actions, and other user interactions with your application.

Event filters enable you to handle an event during the event capturing phase of event processing. A node can have one or more filters for handling an event. A single filter can be used for more than one node and more than one event type. Event filters enable the parent node to provide common processing for its child nodes or to intercept an event and prevent child nodes from acting on the event.

Registering and Removing an Event Filter

To process an event during the event capturing phase, a node must register an event filter. An event filter is an implementation of the EventHandler interface. The handle() method of this interface provides the code that is executed when the event that is associated with the filter is received by the node that registered the filter.

To register a filter, use the addEventFilter() method. This method takes the event type and the filter as arguments. In Example 3-1, the first filter is added to a single node and processes a specific event type. A second filter for handling input events is defined and registered by two different nodes. The same filter is also registered for two different types of events.

Example 3-1 Register a Filter

// Register an event filter for a single node and a specific event type
node.addEventFilter(MouseEvent.MOUSE_CLICKED, 
                    new EventHandler<MouseEvent>() {
                        public void handle(MouseEvent) { ... };
                    });

// Define an event filter
EventHandler filter = new EventHandler(<InputEvent>() {
    public void handle(InputEvent event) {
        System.out.println("Filtering out event " + event.getEventType()); 
        event.consume();
    }

// Register the same filter for two different nodes
myNode1.addEventFilter(MouseEvent.MOUSE_PRESSED, filter);
myNode2.addEventFilter(MouseEvent.MOUSE_PRESSED, filter);

// Register the filter for another event type
myNode1.addEventFilter(KeyEvent.KEY_PRESSED, filter);

Note that an event filter that is defined for one type of event can also be used for any subtypes of that event. See Event Types for information on the hierarchy of event types.

When you no longer want an event filter to process events for a node or for an event type, remove the filter using the removeEventFilter() method. This method takes the event type and the filter as arguments. In Example 3-2, the filter defined in Example 3-1 is removed from the MouseEvent.MOUSE_PRESSED event for myNode1. The filter is still executed by myNode2 and by myNode1 for the KeyEvent.KEY_PRESSED event.

Example 3-2 Remove a Filter

// Remove an event filter
myNode1.removeEventFilter(MouseEvent.MOUSE_PRESSED, filter);

Using Event Filters

Event filters are typically used on a branch node of the event dispatch chain and are called during the event capturing phase of event handling. Use a filter to perform actions such as overriding an event response or blocking an event from reaching its destination.

To see an example of how filters can be used, download the DraggablePanelsExample.zip file. Extract the NetBeans project and open it in the NetBeans IDE. The following sections describe the filters that are used by this example.

Draggable Panels Example

The Draggable Panels example demonstrates the following uses of filters:

  • Registering a filter for a super-type event to provide common handling for subtype events

  • Consuming an event to prevent a child node from acting on it

Figure 3-1 is the screen that is shown when the Draggable Panels example is started. The user interface consists of three panels. Each panel contains different UI controls. At the bottom of the screen is a check box that controls whether the panels can be dragged.

Figure 3-1 Initial Screen for the Draggable Panels Example

Description of Figure 3-1 follows
Description of "Figure 3-1 Initial Screen for the Draggable Panels Example"

If the check box is not selected, clicking any of the controls in the panels generates a response from the control. If the check box is selected, the individual controls do not respond to mouse clicks. Instead, clicking anywhere within a panel and dragging the mouse moves the entire panel, enabling you to change the position of the panels as shown in Figure 3-2.

Figure 3-2 Screen with Repositioned Panels

Description of Figure 3-2 follows
Description of "Figure 3-2 Screen with Repositioned Panels"

Filters for the Draggable Panels Example

In the Draggable Panels example, the makeDraggable() method is used in the creation of the three panels to make each panel movable. This method and the filter definitions are shown in Example 3-3.

Example 3-3 Filter Definitions in makeDraggable()

private Node makeDraggable(final Node node) {
    final DragContext dragContext = new DragContext();
    final Group wrapGroup = new Group(node);
 
    wrapGroup.addEventFilter(
        MouseEvent.ANY,
        new EventHandler<MouseEvent>() {
            public void handle(final MouseEvent mouseEvent) {
                if (dragModeActiveProperty.get()) {
                    // disable mouse events for all children
                    mouseEvent.consume();
                }
             }
        });
 
    wrapGroup.addEventFilter(
        MouseEvent.MOUSE_PRESSED,
        new EventHandler<MouseEvent>() {
            public void handle(final MouseEvent mouseEvent) {
                if (dragModeActiveProperty.get()) {
                    // remember initial mouse cursor coordinates
                    // and node position
                    dragContext.mouseAnchorX = mouseEvent.getX();
                    dragContext.mouseAnchorY = mouseEvent.getY();
                    dragContext.initialTranslateX =
                        node.getTranslateX();
                    dragContext.initialTranslateY =
                        node.getTranslateY();
                }
            }
        });
 
    wrapGroup.addEventFilter(
        MouseEvent.MOUSE_DRAGGED,
        new EventHandler<MouseEvent>() {
            public void handle(final MouseEvent mouseEvent) {
                if (dragModeActiveProperty.get()) {
                    // shift node from its initial position by delta
                    // calculated from mouse cursor movement
                    node.setTranslateX(
                        dragContext.initialTranslateX
                            + mouseEvent.getX()
                            - dragContext.mouseAnchorX);
                    node.setTranslateY(
                        dragContext.initialTranslateY
                            + mouseEvent.getY()
                            - dragContext.mouseAnchorY);
                }
            }
        });
 
    return wrapGroup;

}

Filters for the following events are defined and registered for each panel:

  • MouseEvent.ANY. This filter processes all mouse events for the panel. If the Drag Mode check box is selected, the filter consumes the event, and the child nodes, which are the UI controls within the panel, do not receive the event. If the check box is not selected, the control at the location of the mouse cursor processes the event.

  • MouseEvent.MOUSE_PRESSED. This filter processes only mouse-pressed events for the panel. If the Drag Mode check box is selected, the current location of the mouse is stored.

  • MouseEvent.MOUSE_DRAGGED. This filter processes only mouse-dragged events for the panel. If the Drag Mode check box is selected, the panel is moved.

Note that a panel has three registered filters. Filters for specific event types are invoked before super-type events, so the filters for MouseEvent.MOUSE_PRESSED and MouseEvent.MOUSE_DRAGGED are invoked before the filter for MouseEvent.ANY.

Additional Resources

For information on event filters, see the JavaFX API documentation.

Previous
Next