Arkadeusz91
Arkadeusz91

Reputation: 89

Populate Java FX combobox with a List<String>

I have issues with populating comboBox in JavaFX with values in a list. I am very green with UI development so nothing I found online was really helpful to me. Now I have a Class myClass with a method getNames() that returns List<String>. Now I need the names form that method to be selectable from the dropdown menu. I tried something like this in my Controller :

ObservableList<String> options = FXCollections.observableArrayList(myClass.getNames());

@FXML
final ComboBox comboBox = new ComboBox(options);

but when I launch my program my comboBox is still empty. Of course I also put fx:id = "comboBox" in .fxml file. Did I miss something or should I do that with a completely different method?

Upvotes: 0

Views: 2344

Answers (2)

Slaw
Slaw

Reputation: 45806

Your ComboBox is annotated with @FXML which means an instance will be injected by the FXMLLoader. This injected instance will replace the instance you have created. You should instead populate the ComboBox from the initialize method (see Introduction to FXML).

import javafx.scene.control.ComboBox;

public class Controller {

    @FXML 
    private ComboBox<String> comboBox;

    @FXML
    private void initialize() {
        // Must declare myClass instance somewhere
        comboBox.getItems().setAll(myClass.getNames());
    }

}

Notice I also made the ComboBox generic (and non-final). Avoid using raw types.


While the above is true, your use of final complicates things. From some quick testing it appears the FXMLLoader does not attempt to inject final fields (which makes sense). However, the ComboBox you've created is not the same one that was added to the scene-graph. In other words, the FXMLLoader still creates its own ComboBox which is the one used for building the GUI.

Upvotes: 3

Mark
Mark

Reputation: 5239

From Creating JavaFX user interfaces using FXML | CalliCoder:

The FXML loader instantiates the controller class, injects the fields defined in the controller class with objects instantiated from the fxml document and then calls the controller’s initialize() method.

And

The @FXML annotation is mandatory for private member fields of the controller class, otherwise, field injection won’t work. However, it can be omitted for public fields.


With the code below as mentioned in your question, you're trying to set this field, but afterwards this is overridden by the FXMLLoader.

@FXML
final ComboBox comboBox = new ComboBox(options);

You should initialize the variable comboBox to something like this:

@FXML
private ComboBox comboBox;

And afterwards (after it's been injected by the FXMLLoader) set the items of this ComboBox in this method:

@FXML
private void initialize() {

}

Upvotes: 1

Related Questions