In most JavaFX applications we have to react to many user events: The user clicks a button, presses a key, moves the mouse, etc.
This post describes how to handle some of the most common JavaFX events.
Our Example Application

Download Example
FXML and Event Handling
I like to keep the view code nicely separated inside the fxml files (instead of constructing it with Java code). This allows me to work with the Scene Builder for constructing the GUI.
Working with fxml also provides some convenience for event handling: We can choose event handling methods in the Scene Builder directly. Here is an example for handling the action event of a Button:
- Create a handler method in the controller class (the parameter
ActionEventis optional):
@FXML
private void handleButtonAction(ActionEvent event) {
// Button was clicked, do something...
outputTextArea.appendText("Button Action\n");
}
- Select the
Buttonin Scene Builder and choosehandleButtonActionas On Action.

As you can see, this is very simple. But it will not work for all events. For example, the event for selecting a ComboBox item can not be handled this way.
Java 8 and Event Handling
Java 8 lambda expressions and method references improve the event handling code a lot. I will show two variations of how to handle the action event of a Button in Java 8 code:
Option 1: Lambda Expression
Usually inside the initialize() method:
myButton.setOnAction((event) -> {
// Button was clicked, do something...
outputTextArea.appendText("Button Action\n");
});
Option 2: Method Reference
- Define the handler method somewhere in the controller class:
private void handleButtonAction(ActionEvent event) {
// Button was clicked, do something...
outputTextArea.appendText("Button Action\n");
}
- Reference the handler method (usually inside
initialize()):
myButton.setOnAction(this::handleButtonAction);
Examples
For all examples I will use lambda expressions, but you can always use method references or (for most examples) fxml event handling, as shown above.
Button Events
Handling Button events is very easy. Altough there are other events we’ll likely only need ActionEvents.
// Handle Button event.
myButton.setOnAction((event) -> {
System.out.println("Button Action");
});
CheckBox Events
Handling CheckBox events works almost the same as handling Button events. The only difference is that we might need to know the current state of the CheckBox, wheter it is selected or not.
// Handle CheckBox event.
myCheckBox.setOnAction((event) -> {
boolean selected = myCheckBox.isSelected();
System.out.println("CheckBox Action (selected: " + selected + ")");
});
ComboBox Events
For the ComboBox (and later for the ListView) we’ll use a simple model class Person.java with a firstName and lastName property:
Initializing the ComboBox
First, create an instance variable for the ComboBox and an ObservableList in our controller class. Then don’t forget to select the myComboBox variable as fx:id in Scene Builder:
@FXML private ComboBox<Person> myComboBox; private ObservableList<Person> myComboBoxData = FXCollections.observableArrayList();
Second, create some sample data (e.g. in the constructor or initialize method):
// Add some sample data.
myComboBoxData.add(new Person("Hans", "Muster"));
myComboBoxData.add(new Person("Ruth", "Mueller"));
myComboBoxData.add(new Person("Heinz", "Kurz"));
myComboBoxData.add(new Person("Cornelia", "Meier"));
Third, add sample data to the ComboBox. This must be done in the initialize() method as this is the time when we can be shure that the variable myComboBox is initialized with the ComboBox from the fxml file.
// Init ComboBox items. myComboBox.setItems(myComboBoxData);
ComboBox Rendering
The ComboBox needs to know how to render our Person objects. This is a bit more work:
// Define rendering of the list of values in ComboBox drop down.
myComboBox.setCellFactory((comboBox) -> {
return new ListCell<Person>() {
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getFirstName() + " " + item.getLastName());
}
}
};
});
// Define rendering of selected value shown in ComboBox.
myComboBox.setConverter(new StringConverter<Person>() {
@Override
public String toString(Person person) {
if (person == null) {
return null;
} else {
return person.getFirstName() + " " + person.getLastName();
}
}
@Override
public Person fromString(String personString) {
return null; // No conversion fromString needed.
}
});
Handling Selection Events
Finally, we can handle the selection events:
// Handle ComboBox event.
myComboBox.setOnAction((event) -> {
Person selectedPerson = myComboBox.getSelectionModel().getSelectedItem();
System.out.println("ComboBox Action (selected: " + selectedPerson.toString() + ")");
});
Hyperlink Events
Hyperlinks can be used the same way as a Button.
// Handle Hyperlink event.
myHyperlink.setOnAction((event) -> {
System.out.println("Hyperlink Action");
});
ListView Events
We’ll use the same Person.java class as we used for the ComboBox above.
Initializing the ListView
@FXML private ListView<Person> myListView; private ObservableList<Person> listViewData = FXCollections.observableArrayList();
Add some example data (e.g. in the constructor or initialize method):
// Add some sample data.
listViewData.add(new Person("Lydia", "Kunz"));
listViewData.add(new Person("Anna", "Best"));
listViewData.add(new Person("Stefan", "Meier"));
listViewData.add(new Person("Martin", "Mueller"));
Handling Selection Events
Now, we add the sample data into the ListView and handle the selection events. This must be in the initialize() method as this is the time when we can be shure that the variable myListView is initialized with the ListView from the fxml file.
ListView does not have ActionEvents. Instead it has a selectedItemProperty that contains the currenty selected item of the list.
In JavaFX a Property is more than just a simple value. Each Property provides methods to observe changes made to its value. We can “listen for changes”. This is how we handle such changes for a ListView:
// Init ListView.
myListView.setItems(listViewData);
myListView.setCellFactory((list) -> {
return new ListCell<Person>() {
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getFirstName() + " " + item.getLastName());
}
}
};
});
// Handle ListView selection changes.
myListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("ListView Selection Changed (selected: " + newValue.toString() + ")");
});
The Change Listener Explained
Listening to changes as seen in the ListView example above, follows the same pattern for every other ChangeListener:
-
.selectedItemProperty()gives us access to theProperty.
Note: There are many otherPropertieslikefocusedProperty()ordisabledProperty(). We could use any of those properties and add aChangeListenerto it. -
addListener(...)expects aChangeListener.ChangeListeneris a FunctionalInterface which means we can use lambda expressions here. -
The lambda expression
(observable, oldValue, newValue) -> {...}is where we put our handler code. Every time a change occurs, our lambda expression gets called with the three parameters.
Slider Events
For tracking Slider changes we need a ChangeListener as seen above for the ListView. The Slider has a valueProperty that contains the current value.
// Handle Slider value change events.
mySlider.valueProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Slider Value Changed (newValue: " + newValue.intValue() + ")");
});
TextBox Events
In a TextBox the ActionEvent is triggered with the return key. We might use this, but probably the most common case is that we must react to changes made to the text.
We’ll use a ChangeListener as described above in the ListView section.
// Handle TextField text changes.
myTextField.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("TextField Text Changed (newValue: " + newValue + ")");
});
// Handle TextField enter key event.
myTextField.setOnAction((event) -> {
System.out.println("TextField Action");
});
Additional Info
For more information turn to the official JavaFX Events Tutorial (does not cover fxml).