12.5. Events and Event Handlers¶
In JavaFX, nodes can generate
Event
objects. This can happen automatically or in response to user input.
Each event has a corresponding event handler, i.e., a method that is
registered to handle the event when it is generated. Let’s add a button
to ExampleApp
, then register an event handler for one of the events
the button might generate.
In
ExampleApp.java
, import the Button class, then add the following line immediately after the line that creates theText
object:Button button = new Button("Click me!");
This creates a
Button
object; however, it will NOT automatically appear in the app’s GUI!To add the
Button
object to the GUI, you need to add it to the scene. Here, we will add the button as a child of theHBox
object already contained in the scene graph. This can be accomplished by adding the following line immediately after the line that adds theText
object to theHBox
:root.getChildren().add(button);
If you are adding multiple children to a node, you may prefer to use the variadic method
addAll
instead ofadd
on theObservableList<Node>
returned by thegetChildren
method.Compile
ExampleApp.java
, then rerunExampleDriver
. You should now see the button!Move your mouse over the button. You should notice that the styling of the button changes automatically as your mouse cursor enters and leaves the visual area of the button (the change is very subtle; look closely). Click on the button. Similarly, the styling of the button will change. As you interact with the button, you are actually causing the button to generate events! These events have default event handlers that cause the button’s style to change.
When a user clicks on a button, that causes the button to generate an ActionEvent object. You can register an event handler for this event by calling the
setOnAction
method. Here is the signature of thesetOnAction
method:public final void setOnAction(EventHandler<ActionEvent> value)
As you can see, to call the
setOnAction
method, we will need to supply a reference to anEventHandler<ActionEvent>
object. It turns out that EventHandler<T> is an interface. This gives us many options. It also turns out that this interface is a functional interface, which means that we can use a lambda expression. We point out thatEventHandler<T>
is an interface before to remind you that you can always implement the interface in the usual way instead of using a lambda expression. Let’s create a handler that prints a message to standard output whenever the user clicks on the button.Let’s implement the
EventHandler<ActionEvent>
using a lambda expression. To do this, consult the API documentation for the interface and inspect its abstracthandle
method. The lambda expression will represent that method. Import the relevant types, then add the following line directly below the line where you created the button:EventHandler<ActionEvent> buttonHandler = event -> System.out.println("you clicked me!");
The previous step only created the
EventHandler<ActionEvent>
object. Now we need to register it with the button using thesetOnAction
method. Add the following line directly below the line you added in the previous step:button.setOnAction(buttonHandler);
Compile
ExampleApp.java
, then rerunExampleDriver
. Click on the button! If you followed the steps correctly, then you should see the textyou clicked me!
appear in your terminal window.Congratulations! You have successfully created your first interactive GUI app! The next step is to add more nodes/components to the scene graph, and then register event handlers that cause changes in those components instead of merely printing a message to standard output. This will be explored in the class exercises and some of your projects.