JavaFX

JavaFX Event Example

This is a JavaFX Event Example. In general, the term event is used to describe an occurrence of interest. In a GUI application, an event is an occurrence of a user interaction with the application. Clicking the mouse and pressing a key on the keyboard are examples of events in a JavaFX application.
 
 
 
 
 
 
 
 

 
The following table shows an overview of the whole article:

The following examples uses Java SE 7 and JavaFX 2.2.

1. Introduction

An event in JavaFX is represented by an object of the javafx.event.Event class or any of its subclasses.

Every event in JavaFX has three properties:

  • An event source
  • An event target
  • An event type

When an event occurs in an application, you typically perform some processing by executing a piece of code. The piece of code that is executed in response to an event is known as an event handler or an event filter. When you want to handle an event for a UI element, you need to add event handlers to the UI element, for example, a Window, a Scene, or a Node. When the UI element detects the event, it executes your event handlers.

The UI element that calls event handlers is the source of the event for those event handlers. When an event occurs, it passes through a chain of event dispatchers. The source of an event is the current element in the event dispatcher chain. The event source changes as the event passes through one dispatcher to another in the event dispatcher chain.

The event target is the destination of an event. The event target determines the route through which the event travels during its processing. Suppose a mouse click occurs over a Circle node. In this case, the Circle node is the event target of the mouse-clicked event.

The event type describes the type of the event that occurs. Event types are defines in a hierarchical fashion. Each event type has a name and a supertype.

The three properties that are common to all events in JavaFX are represented by objects of three different classes. Specific events define additional event roperties. For example, the event class to represent a mouse event adds properties to describe the location of the mouse cursor, state of the mouse buttons, among others.

2. Event Class Hierarchy

The Event class provides properties and methods that are common to all events. The getSource() method returns an Object, which is the source of the event. The Event class inherits this method from the EventObject class. The getTarget() method returns an instance of the EventTarget interface, which is the target of the event. The getEventType() method returns an object of the EventType class, which indicates the type of the event.

The Event class contains consume() and isConsumed() methods. As noted before, an event travels from one element to another in an event-dispatching chain. Calling the consume() method on an Event object indicates that the event has been consumed and no further processing is required. After the consume() method is called, the event does not travel to the next element in the event-processing chain. The isConsumed() method returns true if the consume() method has been called, otherwise, it returns false.

Specific Event subclasses define more properties and methods. For example, the MouseEvent class defines getX() and getY() methods that return the x and y coordinates of the mouse cursor relative to the source of the event.

3. Event Targets

An event target is a UI element that can respond to events. Technically, a UI element that wants to respond to events must implement the EventTarget interface. That is, in JavaFX, implementing the EventTarget interface makes a UI element eligible to be an event target.

The Window, Scene, and Node classes implement the EventTarget interface. This means that all nodes, including windows and scenes, can respond to events. The classes for some UI elements, for example, Tab, TreeItem, and MenuItem, do not inherit from the Node class. They can still respond to events because they implement the EventTarget interface. If you develop a custom UI element, you will need to implement this interface if you want your UI element to respond to events.

The responsibility of an event target is to build a chain of event dispatchers, which is also called the event route. An event dispatcher is an instance of the EventDispatcher interface. Each dispatcher in the chain can affect the event by handling and consuming. An event dispatcher in the chain can also modify the
event properties, substitute the event with a new event, or chain the event route.

Typically, an event target route consists of dispatchers associated with all UI elements in the container-child hierarchy. Suppose you have a Circle node placed in an HBox, which is placed in a Scene. The Scene is added to a Stage. If the mouse is clicked on the Circle, the Circle becomes the event target. The Circle builds an event dispatcher chain whose route will be, from head to tail, the Stage, Scene, HBox, and Circle.

4. Event Types

An instance of the EventType class defines an event type. Why do you need a separate class to define event types? Aren’t separate event classes, for example, KeyEvent, MouseEvent, for each event sufficient to define event types? Can’t you distinguish one event from another based on the event class? The EventType class is used to further classify the events within an event class. For example, the MouseEvent class only tells us that the user has used the mouse. It does not tell us the details of the mouse use, for example, whether the mouse was pressed, released, dragged, or clicked.

The EventType class is used to classify these subevent types of an event. The EventType class is a generic class whose type parameter is defined as follows:

EventType<T extends Event>

Event types are hierarchical. They are hierarchical by implementation, not by class inheritance. Each event type has a name and a supertype. The getName() and setSuperType() methods in the EventType class return the name and supertype of an event type. The constant Event.ANY, which is the same as the constant EventType.ROOT, is the supertype of all events in JavaFX.

5. Event Processing Mechanism

When an event occurs, several steps are performed as part of the event processing:

  • Event target selection
  • Event route construction
  • Event route traversal

5.1 Event Target Selection

The first step in the event processing is the selection of the event target. Recall that an event target is the destination node of an event. The event target is selected based on the event type.

For mouse events, the event target is the Node at the mouse cursor. Multiple nodes can be available at the mouse cursor. For example, you can have a Circle placed over a Rectangle. The topmost node at the mouse cursor is selected as the event target.

The event target for key events is the node that has focus. How a node gets the focus depends on the type of the node. For example, a TextField may gain focus by clicking the mouse inside it or using the focus traversal keys such as Tab or Shift + Tab on the Windows format. Shapes such as Circles or Rectangles do not get focus by default.

If you want them to receive key events, you can give them focus by calling the
requestFocus() method of the Node class.

JavaFX supports touch and gesture events on touch-enabled devices. A touch event is generated by touching a touch screen. Each touch action has a point of contact called a touch point. It is possible to touch a touch screen with multiple fingers, resulting in multiple touch points. Each state of a touch point, for example, pressed, released, and so forth, generates a touch event. The location of the touch point determines the target of the touch event. For example, if the location of the touch event is a point within a circle, the circle becomes the target of the touch event. In case of multiple nodes at the touch point, the topmost node is selected as the target.

Users can interact with a JavaFX application using gestures. Typically, a gesture on a touch screen and a track pad consists of multiple touch points with touch actions. Examples of gesture events are rotating, scrolling, swiping, and zooming. A rotating gesture is performed by rotating two fingers around each other.

A scrolling gesture is performed by dragging a finger on touch screen. A swiping gesture is performed by dragging a finger on the touch screen in one direction. A zooming gesture is performed to scale a node by dragging two fingers apart or closer.

The target for gesture events are selected depending on the type of gesture. For direct gestures, for example, gestures performed on touch screens, the topmost node at the center point of all touch points at the start of the gesture is selected as the event target. For indirect gestures, for example, gestures performed on a track pad, the topmost node at the mouse cursor is selected as the event target.

5.2 Event Route Construction

An event travels through event dispatchers in an event dispatch chain. The event dispatch chain is the event route. The initial and default routes for an event are determined by the event target. The default event route consists of the container-children path starting at the stage to the event target node.

Suppose you have placed a Circle and a Rectangle in an HBox and the HBox is the root node of the Scene of a Stage. When you click the Circle, the circle becomes the event target. The Circle constructs the default event route, which is the path starting at the stage to the event target (the circle).

In fact, an event route consists of event dispatchers that are associated with nodes. However, for all practical and understanding purposes, you can think of the event route as the path comprising the nodes.

Typically, you do not deal with event dispatchers directly.

5.3 Event Route Traversal

An event route traversal consists of two phases:

  • Capture phase
  • Bubbling phase

An event travels through each node in its route twice: once during the capture phase and once during the bubbling phase. You can register event filters and event handlers to a node for specific events types.

The event filters and event handlers registered to a node are executed as the event passes through the node during the capture phase and the bubbling phase, respectively. The event filters and handlers are passed in the reference of the current node as the source of the event. As the event travels from one node to another, the event source keeps changing. However, the event target remains the same from the start to the finish of the event route traversal.

During the route traversal, a node can consume the event in event filters or handlers, thus completing the processing of the event. Consuming an event is simply calling the consume() method on the event object.

When an Event is consumed, the event processing is stopped, even though some of the nodes in the route were not traversed at all.

6. Handling Events

6.1 The Code

FxEventExample1.java

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class FxEventExample1 extends Application
{
	// Create the LoggingArea
	private TextArea loggingArea = new TextArea("");

	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create a coral Circle
		Circle circle = new Circle (150, 150, 50);
		circle.setFill(Color.CORAL);
		
		// Create a MouseEvent filter
		EventHandler<MouseEvent> mouseEventFilter = new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	writelog("Mouse event filter has been called");
            }
        };				
					
		// Create a MouseEvent handler
		EventHandler<MouseEvent> mouseEventHandler = new EventHandler<MouseEvent>() 
		{
            public void handle(MouseEvent event) 
            {
            	writelog("Mouse event handler has been called");
            }
        };				
        	
		// Register the MouseEvent filter and handler to the Circle for mouse-clicked events
		circle.addEventFilter(MouseEvent.MOUSE_CLICKED, mouseEventFilter);
		circle.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEventHandler);
		
		// Create the VBox
		VBox root = new VBox();
		// Add the children to the VBox
		root.getChildren().addAll(circle, loggingArea);
		
		// Set the Padding and Border for the VBox
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root, 400,300);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("An Example about Registering Event Filters and Handlers");
		// Display the Stage
		stage.show();
	}

	// Helper Method for Logging
	private void writelog(String text)
	{
		this.loggingArea.appendText(text + "\n");
	}
	
}

FxEventExample2.java

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class FxEventExample2 extends Application
{
	// Create the LoggingArea
	private TextArea loggingArea = new TextArea("");

	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create a coral Circle
		Circle circle = new Circle (150, 150, 50);
		circle.setFill(Color.CORAL);
		
		// Create the VBox
		VBox root = new VBox();
		// Add the children to the VBox
		root.getChildren().addAll(circle, loggingArea);
		
		// Set the Padding and Border for the VBox
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		
		// Register three handlers for the circle that can handle mouse-clicked events //
		// This will be called last
		circle.addEventHandler(MouseEvent.ANY, new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleAnyMouseEvent(event);
            }
        });
		
		// This will be called first
		circle.addEventHandler(MouseEvent.MOUSE_CLICKED,  new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleMouseClicked("addEventHandler()", event);
            }
        });
		
		// This will be called second
		circle.setOnMouseClicked(new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleMouseClicked("setOnMouseClicked()", event);
            }
        });
		
		// Add the Stage to the Scene
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("An Example about the Execution Order of Events");
		// Display the Stage
		stage.show();
	}

	public void handleMouseClicked(String registrationMethod, MouseEvent e) 
	{
		// Print a message for a mouse click
		this.loggingArea.appendText(registrationMethod
			+ ": MOUSE_CLICKED handler detected a mouse click.\n");
	}
	
	public void handleAnyMouseEvent(MouseEvent e) 
	{
		// Print a message only for mouse-clicked events, ignoring
		// other mouse events such as mouse-pressed, mouse-released, etc.
		if (e.getEventType() == MouseEvent.MOUSE_CLICKED) 
		{
			this.loggingArea.appendText("MouseEvent.ANY handler detected a mouse click.\n");
		}
	}	
}

Handling an event means executing the application logic in response to the occurrence of the event. The application logic is contained in the event filters and handlers, which are objects of the EventHandler interface, as shown in the following code:

public interface EventHandler<T extends Event> extends EventListener
{
void handle(T event);
}

The EventHandler class is a generic class in the javafx.event package. It extends the EventListener marker interface, which is in the java.util package. The handle() method receives the reference of the event object, for example, the reference of the KeyEvent, MouseEvent, among others.

Both event filters and handlers are objects of the same EventHandler interface. You cannot tell whether an EventHandler object is an event filter or an event handler by just looking at it. In fact, you can register the same EventHandler object as event filters as well as handlers at the same time. The distinction between the two is made when they are registered to a node. Nodes provide different methods to register them. Internally, nodes know whether an EventHandler object was registered as an event filter or a handler.

Another distinction between them is made based on the event traversal phase in which they are called. During the event capture phase, the handle() method of registered filters is called, whereas the handle() method of registered handlers is called in the event bubbling phase.

6.2 Creating Event Filters and Handlers

Creating event filters and handlers is as simple as creating objects of the class that implement the EventHandler interface.

EventHandler<MouseEvent> handler = new EventHandler<MouseEvent>() 
{
	@Override
	public void handle(MouseEvent e) 
	{
		/* Event handling code goes here */
	}
};

6.3 Registering Event Filters and Handlers

If you want a node to process events of specific types, you need to register event filters and handlers for those event types to the node. When the event occurs, the handle() method of the registered event filters and handlers for the node are called following the rules discussed in the previous sections. If the node is no longer interested in processing the events, you need to unregister the event filters and handlers from the node.

Registering and unregistering event filters and handlers are also known as adding and removing event filters and handlers, respectively.

JavaFX provides two ways to register and unregister event filters and handlers to nodes:

  • Using the addEventFilter(), addEventHandler(), removeEventFilter(), and removeEventHandler() methods
  • Using the onXXX convenience properties

6.3.1 Using addXXX() and removeXXX() Methods

You can use the addEventFilter() and addEventHandler() methods to register event filters and handlers to nodes, respectively. These methods are defined in the Node class, Scene class, and Window class. Some classes can be event targets. However, they are not inherited from the Node class. The classes provide only the addEventHandler() method for event handlers registration, such as:

  • <T extends Event> void addEventFilter(EventType<T> eventType, EventHandler<? super T> eventFilter)
  • <T extends Event> void addEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler)

These methods have two parameters. The first parameter is the event type and the second is an object of the EventHandler interface.

You can handle mouse-clicked events for a Circle using the following snippet of code:

// Create a coral Circle
Circle circle = new Circle (150, 150, 50);
circle.setFill(Color.CORAL);

// Create a MouseEvent filter
EventHandler<MouseEvent> mouseEventFilter = new EventHandler<MouseEvent>()
{
	public void handle(MouseEvent event) 
	{
		writelog("Mouse event filter has been called");
	}
};				

// Create a MouseEvent handler
EventHandler<MouseEvent> mouseEventHandler = new EventHandler<MouseEvent>() 
{
	public void handle(MouseEvent event) 
	{
		writelog("Mouse event handler has been called");
	}
};				

// Register the MouseEvent filter and handler to the Circle for mouse-clicked events
circle.addEventFilter(MouseEvent.MOUSE_CLICKED, mouseEventFilter);
circle.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEventHandler);

This code creates two EventHandler objects, which prints a message on the console. At this stage, they are not event filters or handlers. They are just two EventHandler objects. Note that giving the reference variables names and printing messages that use the words filter and handler does not make any difference in their status as filters and handlers. The last two statements register one of the EventHandler objects as an event filter and another as an event handler. Both are registered for the mouse-clicked event.

// Create a MouseEvent handler
EventHandler<MouseEvent> mouseEventHandler = new EventHandler<MouseEvent>() 
{
	public void handle(MouseEvent event) 
	{
		writelog("Mouse event handler has been called");
	}
};				

// Register the MouseEvent filter and handler to the Circle for mouse-clicked events
circle.addEventFilter(MouseEvent.MOUSE_CLICKED, mouseEventFilter);
circle.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEventHandler);

Registering the same EventHandler object as event filters as well as handlers is allowed.

To unregister an event filter and an event handler, you need to call the removeEventFilter() and removeEventHandler() methods, respectively:

  • <T extends Event> void removeEventFilter(EventType<T> eventType, EventHandler<? super T> eventFilter)
  • <T extends Event> void removeEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler)

6.3.3 Using onXXX Convenience Properties

The Node, Scene, and Window classes contain event properties to store event handlers of some selected event types. The property names use the event type pattern. They are named as onXXX.

For example, the onMouseClicked property stores the event handler for the mouse-clicked event type, the onKeyTyped property stores the event handler for the key-typed event, and so on. You can use the setOnXXX() methods of these properties to register event handlers for a node.

For example, use the setOnMouseClicked() method to register an event handler for the mouse-clicked event and use the setOnKeyTyped() method to register an event handler for the key-typed event, and so on. The setOnXXX() methods in various classes are known as convenience methods for registering event handlers.

You need to remember some points about the onXXX convenience properties:

  • They only support the registration of event handlers, not event filters. If you need to register event filters, use the addEventFilter() method.
  • They only support the registration of one event handler for a node. Multiple event handlers for a node may be registered using the addEventHandler() method.
  • These properties exist only for the commonly used events for a node type. For example, the onMouseClicked property exists in the Node and Scene classes, but not the Window class; the onShowing property exists in the Window class, but not in the Node and Scene classes.

The class FxEventExample1 works the same as the FxEventExample2. In the sceond example, you have used the onMouseClicked property of the Node class to register the mouse-clicked event handler for the circle.

Notice that to register the event filter, you have to use the addEventFilter() method as before.

The convenience event properties do not provide a separate method to unregister the event handler.

Setting the property to null unregisters the event handler that has already been registered:

// Register an event handler for the mouse-clicked event
circle.setOnMouseClicked(eventHandler);

...

// Later, when you are no longer interested in processing the mouse-clicked event, unregister it.
circle.setOnMouseClicked(null);

Classes that define the onXXX event properties also define getOnXXX() getter methods that return the reference of the registered event handler. If no event handler is set, the getter method returns null.

6.4 The GUI

The following image shows the GUI of the first program:

A JavaFX Example about Registering Event Filters and Handlers
A JavaFX Example about Registering Event Filters and Handlers

Run the second program and click inside the circle. You will get the same output you got when running the first program.

A JavaFX Example about the Execution Order of Events
A JavaFX Example about the Execution Order of Events

7. Execution Order of Event Filters and Handlers

7.1 The Code

FxEventExample3.java

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import static javafx.scene.input.MouseEvent.MOUSE_CLICKED;
import javafx.scene.control.TextArea;

public class FxEventExample3 extends Application
{
	// Create the LoggingArea
	private TextArea loggingArea = new TextArea("");

	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create a Circle
		Circle circle = new Circle (50, 50, 50);
		circle.setFill(Color.CORAL);
		
		// Create a Rectangle
		Rectangle rectangle = new Rectangle(100, 100);
		rectangle.setFill(Color.TAN);
		
		// Create the HBox
		HBox hbox = new HBox();
		// Set Padding and Spacing of the HBox
		hbox.setPadding(new Insets(20));
		hbox.setSpacing(20);
		
		// Add the children to the HBox
		hbox.getChildren().addAll(circle, rectangle);
		
		// CReate the VBox
		VBox root = new VBox();
		// Set Padding and Spacing of the VBox
		root.setPadding(new Insets(20));
		root.setSpacing(20);

		// Add the children to the VBox
		root.getChildren().addAll(hbox, loggingArea);
		
		// Create the Scene
		Scene scene = new Scene(root);
		
		// Create two EventHandlders
		EventHandler<MouseEvent> filter = new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleEvent("Capture",event);
            }
        };				
					
		EventHandler<MouseEvent> handler = new EventHandler<MouseEvent>() 
		{
            public void handle(MouseEvent event) 
            {
            	handleEvent("Bubbling",event);
            }
        };				
		
		// Register the Event Filters
		stage.addEventFilter(MOUSE_CLICKED, filter);
		scene.addEventFilter(MOUSE_CLICKED, filter);
		root.addEventFilter(MOUSE_CLICKED, filter);
		circle.addEventFilter(MOUSE_CLICKED, filter);
		
		// Register the Event Handlers
		stage.addEventHandler(MOUSE_CLICKED, handler);
		scene.addEventHandler(MOUSE_CLICKED, handler);
		root.addEventHandler(MOUSE_CLICKED, handler);
		circle.addEventHandler(MOUSE_CLICKED, handler);
		
		// Set the Padding and Border for the VBox
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("An Example about Event Capture and Bubbling");
		// Display the Stage
		stage.show();
	}

	// Helper Method for Event-Handling
	public void handleEvent(String phase, MouseEvent e) 
	{
		// Get type, source and target of the Event
		String type = e.getEventType().getName();
		String source = e.getSource().getClass().getSimpleName();
		String target = e.getTarget().getClass().getSimpleName();
	
		// Get coordinates of the mouse cursor relative to the Event Source
		double x = e.getX();
		double y = e.getY();
		
		// Log the Informations
		this.loggingArea.appendText(phase + ": Type=" + type +
			", Target=" + target + ", Source=" + source +
			", location(" + x + ", " + y + ")\n");
	}
	
}

There are some execution order rules for event filters and handlers for both similar and different nodes:

Event filters are called before event handlers. Event filters are executed from the
topmost parent to the event target in the parent-child order. Event handlers are executed in the reverse order of the event filters. That is, the execution of the event andlers starts at the event target and moves up in the child-parent order.

For the same node, event filters and handlers for a specific event type are called before the event filters and handlers for generic types. Suppose you have registered event handlers to a node for MouseEvent.ANY and MouseEvent.MOUSE_CLICKED. Event handlers for both event types are capable of handling mouse-clicked events. When the mouse is clicked on the node, the event handler for the MouseEvent.MOUSE_CLICKED event type is called before the event handler for the MouseEvent.ANY event type. Note that a mouse-pressed event and a mouse-released event occur before a mouse-clicked event occurs. In our example, these events will be handled by the event handler for the MouseEvent.ANY event type.

The order in which the event filters and handlers for the same event type for a node are executed is not specified. There is one exception to this rule. Event handlers registered to a node using the addEventHandler() method are executed before the event handlers registered using the setOnXXX() convenience methods.

7.2 The GUI

The above program demonstrates the execution order of the event filters and handlers for different nodes. The program adds a Circle and a Rectangle to an HBox. An event filter and an event handler are added to the Stage, Scene, HBox, and Circle for the mouse-clicked event.

Run the program and click anywhere inside the circle. The output shows the order in which filters and handlers are called. The output contains the event phase, type, target, source, and location.

A JavaFX Example about Event Capture and Bubbling
A JavaFX Example about Event Capture and Bubbling

8. Consuming Events

8.1 The Code

FxEventExample4.java

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.input.MouseEvent;
import static javafx.scene.input.MouseEvent.MOUSE_CLICKED;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.control.TextArea;

public class FxEventExample4 extends Application
{
	// Create the CheckBox
	private CheckBox consumeEventCbx = new CheckBox("Consume Mouse Click at Circle");	
	// Create the LoggingArea
	private TextArea loggingArea = new TextArea("");

	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create a Circle
		Circle circle = new Circle (50, 50, 50);
		circle.setFill(Color.CORAL);
		
		// Create a Rectangle
		Rectangle rectangle = new Rectangle(100, 100);
		rectangle.setFill(Color.TAN);
		
		// Create the HBox
		HBox hbox = new HBox();
		// Set Padding and Spacing of the HBox
		hbox.setPadding(new Insets(20));
		hbox.setSpacing(20);
		
		// Add the children to the HBox
		hbox.getChildren().addAll(circle, rectangle, consumeEventCbx);

		// CReate the VBox		
		VBox root = new VBox();
		// Set Padding and Spacing of the VBox
		root.setPadding(new Insets(20));
		root.setSpacing(20);

		// Add the children to the VBox
		root.getChildren().addAll(hbox, loggingArea);
		
		// Create the Scene
		Scene scene = new Scene(root);

		// Register mouse-clicked event handlers to all nodes,
		// except the rectangle and CheckBox
		EventHandler<MouseEvent> handler = new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleEvent(event);
            }
        };
        
		EventHandler<MouseEvent> circleMeHandler = new EventHandler<MouseEvent>()
		{
            public void handle(MouseEvent event) 
            {
            	handleEventforCircle(event);
            }
        };
		
        // Add the Event Handler
		stage.addEventHandler(MOUSE_CLICKED, handler);
		scene.addEventHandler(MOUSE_CLICKED, handler);
		root.addEventHandler(MOUSE_CLICKED, handler);
		circle.addEventHandler(MOUSE_CLICKED, circleMeHandler);

		// Set the Padding and Border for the VBox
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("An Example about Consuming Events");
		// Display the Stage
		stage.show();
	}

	// Helper Method for Event Handling
	public void handleEvent(MouseEvent e) 
	{
		print(e);
	}
	
	public void handleEventforCircle(MouseEvent e) 
	{
		print(e);
	
		if (consumeEventCbx.isSelected()) 
		{
			e.consume();
		}
	}
	
	// Helper Method for Logging
	public void print(MouseEvent e) 
	{
		// Get type, source and target of the Event
		String type = e.getEventType().getName();
		String source = e.getSource().getClass().getSimpleName();
		String target = e.getTarget().getClass().getSimpleName();

		// Get coordinates of the mouse cursor relative to the event source
		double x = e.getX();
		double y = e.getY();
		
		// Log the Informations
		this.loggingArea.appendText("Type=" + type + ", Target=" + target +
				", Source=" + source +
				", location(" + x + ", " + y + ")\n");
	}
	
}

An event is consumed by calling its consume() method. The event class contains the method and it is inherited by all event classes. Typically, the consume() method is called inside the handle() method of the event filters and handlers.

Consuming an event indicates to the event dispatcher that the event processing is complete and that the event should not travel any farther in the event dispatch chain.

If an event is consumed in an event filter of a node, the event does not travel to any child node. If an event is consumed in an event handler of a node, the event does not travel to any parent node.

All event filters or handlers for the consuming node are called, irrespective of which filter or handler consumes the event. Suppose you have registered three event handlers for a node and the event handler, which is called first, consumes the event. In this case, the other two event handlers for the node are still called.

If a parent node does not want its child nodes to respond to an event, it can consume the event in its event filter. If a parent node provides a default response to an event in an event handler, a child node can provide a specific response and consume the event, thus suppressing the default response of the parent.

Typically, nodes consume most input events after providing a default response. The rule is that all event filters and handlers of a node are called, even if one of them consumes the event. This makes it possible for developers to execute their event filters and handlers for a node even if the node consumes the event.

8.2 The GUI

The class FxEventExample4 shows how to consume an event. The following image shows the screen when you run the program.

A JavaFX Example about Consuming Events
A JavaFX Example about Consuming Events

9. Download Source Code

This was an example of javafx.event.Event

Download
You can download the full source code of this example here: JavaFxEventExample.zip

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
arpit
arpit
5 years ago

Thanks a lot.Nice Explanation.

Back to top button