In this tutorial I'll show you a very simple example on how to attach an ObservableList to a ListView and how to perform the basic operations: add, remove or edit an entry.
- We'll start by opening NetBeans, go to New Project and chose JavaFX->JavaFX FXML Application
- Name this project TestListView, or whatever name you like
- I recommend to name the FXML file as the name used at point #2+"UI". eg. mine will be TestListViewUI (UI stands for User Interface, as this is what the FXML contains)
- Click finish and you already have a running application that display a button and a hello world text.
- Let's go to the TestListViewUI.fxml file and double click to open JavaFX Scene Builder
- I was thinking on the following interface:
- A ListView on the left side, a "Delete" button under it and 2 text fields on the right side.
- The ListView will display a list of name and user will be able to see the selected name in the first TextField where he can change it as he wish. Pressing Enter will update the name displayed in the ListView.
- Entering a name in the second TextField and pressing Enter will add this name to the ListView.
- Do you quess what the Delete button do? It will delete the selected name.
- Note: this tutorial is made to present you the techniques used to manipulate a ListView, so is not focused too much on the user interface neither on bugs, as a real program should do. In fact I have intentional left some bugs out there to let you the pleasure of finding and solving them.
- Back to NetBeans to TextViewUIController.java to work on the code behind the user interface
- First is to define the variables that will get connected to the FXML file and second to define the actions behind buttons and textfields.
- to define a variable to be used in FXML, you have to precede with @FXML, then on a new row enter the variable type and name, like you see here:
@FXML
private TextField name;
// this will show the selected name and allow user to change it
@FXML
private TextField newName;
// this will let you enter a new name
@FXML
private ListView listView;
// the list with all the names - to define a method that can be used in FXML you do the same as above at #a:
@FXML
private void changeName(ActionEvent event) {
//TODO - code when Enter is pressed in Selected Name area
}
@FXML
private void addName(ActionEvent event) {
//TODO - code when Enter is pressed in New Name area
}
@FXML
private void delName(ActionEvent event) {
//TODO - code when Delete button is pressed
} - save and then double click on TextListViewUI.fxml to get back into JavaFX Scene Builder
- we have the code behind buttons, so is time to connect them. I'll show you how to proceed for one item and let you do the discovery work for the others.
Select the first TextField, the one under Selected Name text, then go to Properties tab from Inspector Panel (right side of your screen). Chose name at the fx:id as you can see from the picture:
Select the Code tab and chose #changeName at On Action field: - do the same for the ListView, Delete button and the other TextField object, then save and back to NetBeans
- You can run the project and everything should be ok, except that the application is not actually doing anything, as we have just make the connection, we haven't write yet the code for the actions to be performed.
- We'll start by defining an ObservableList that will be later connect to the ListView:
private final ObservableListcurrentList=FXCollections.observableArrayList();
In the initialize method we have to define the action when an item is selected from the ListView:
listView.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener() {
@Override
public void changed(ObservableValue ov, String t, String t1) {
name.setText(t1);
}});
Whenever the user click on an Item from the ListView we'll have access the the previous selected element, this is parameter t, and also to the actual selected element, which is parameter t1. We'll send the text of the selected item (t1) to the first TextField (name).
Don't worry if you don't understand too much from the code, important is to know that you have access to the previous and to the current element of the list and you decide what to do with this information. In our case I'm just sending the value to a TextField, but you could use the values as parameters for your own methods, or just call your own methods whenever user is doing any selection in the ListView. - We'll connect now the ListView with the ObservableList by using the following code:
listView.setItems(currentList); - Time to add something to our list:
currentList.add("John");
currentList.add("Samuel");
currentList.add("Smith");
Did you note that we actually add data inside our ObservableList? - Run the project and voila, you're list is populated with some names and whenever you select something the TextField show this…but still nothing happens on clicking the buttons. We'll solve this right now with the following code that will replace the previous one with //TODO:
@FXML
private void changeName(ActionEvent event) {
/*
* First we need to find out which is the seleted element from our
* ListView. Once we got this and knowing that our ObservableList
* has the same order as the ListView, it's piece of cake to set the
* new value
* NOTE: use set in order to update the ListView, using anything
* else will update your ObservableList but not the ListView
*/
currentList.set(listView.getSelectionModel().getSelectedIndex(),name.getText());
}
@FXML
private void addName(ActionEvent event) {
/*
* Adding a new element to our ObservableList will automatically
* be reflected in ListView
*/
currentList.add(newName.getText());
newName.clear();
}
@FXML
private void delName(ActionEvent event) {
/*
* Deleting an element from our ObservableList will automatically
* be deleted from ListView
* the only problem here is to know the index of the element
* we want to delete
*/
currentList.remove(listView.getSelectionModel().getSelectedIndex());
} - If you miss anything here are the sources of this project.