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 theTextobject:Button button = new Button("Click me!");
This creates a
Buttonobject; however, it will NOT automatically appear in the app’s GUI!To add the
Buttonobject to the GUI, you need to add it to the scene. Here, we will add the button as a child of theHBoxobject already contained in the scene graph. This can be accomplished by adding the following line immediately after the line that adds theTextobject to theHBox:root.getChildren().add(button);
If you are adding multiple children to a node, you may prefer to use the variadic method
addAllinstead ofaddon theObservableList<Node>returned by thegetChildrenmethod.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
setOnActionmethod. Here is the signature of thesetOnActionmethod:public final void setOnAction(EventHandler<ActionEvent> value)
As you can see, to call the
setOnActionmethod, 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 abstracthandlemethod. 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 thesetOnActionmethod. 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.