I have my scene made with JavaFX Scene Builder and ListView in it. I want it to show some data from xml file, but I have no idea how to properly initialize this ListView.
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
import application.Cparsing;
import javafx.collections.*;
public class MainDriversController{
private static ListView<String> driversLV;
static ObservableList<String> observableList = FXCollections.observableArrayList();
public static void SetListView(){
for(int x=0; x<Cparsing.driversNodes.getLength(); x++) {
observableList.add(Cparsing.driversNodes.item(x).getAttributes().getNamedItem("nick").getNodeValue());
}
driversLV.setItems(observableList);
System.out.println(driversLV);
}
}
That of course gives me NullPointerException because it's not initialized. I've tried to add
driversLV = new ListView<String>(observableList);
and no error then, but ListView is still empty in GUI.
System.out.println(driversLV);
gives:
ListView@54f2d1d5[styleClass=list-view]
So my question is: what is the proper way to initialize ListView? Is my code correct despite this?
First, don't make anything here static. The controller is an object associated with the UI loaded from the FXML file, so the fields and methods need to be member of that object, not of the class. (And the FXMLLoader
will not initialize static fields.)
Second, annotate the fields declared in the FXML file with @FXML
. That will allow the FXMLLoader
to initialize them even if you declare them private (which you should do). Make sure the fx:id
assigned to the control in the FXML file is the same as the field name.
Finally, the FXMLLoader
will (by default) create an instance of your controller class by calling its no-argument constructor, then it will initialize the fields. Consequently, of course, they will not be initialized when the constructor is invoked. Instead, use the initialize()
method, which the FXMLLoader
will invoke automatically once the @FXML
-annotated fields have been injected.
So you should have
public class MainDriversController{
@FXML
private ListView<String> driversLV;
private ObservableList<String> observableList = FXCollections.observableArrayList();
@FXML
private void initialize(){
for(int x=0; x<Cparsing.driversNodes.getLength(); x++) {
observableList.add(Cparsing.driversNodes.item(x).getAttributes().getNamedItem("nick").getNodeValue());
}
driversLV.setItems(observableList);
System.out.println(driversLV);
}
}
And of course your FXML file will have fx:controller="my.package.name.MainDriversController"
in the root element, and
<ListView fx:id="driversLV" />
as an element somewhere.