Avinta
Avinta

Reputation: 768

JavaFX - Automatically update a choiceBox

I have a Thread which permantly updates/creates a List:

private ObservableList<String> query() {
    try {
        return FXCollections.observableArrayList(getWMIValue(query, fieldName));
    } catch (Exception e) {
        return FXCollections.observableArrayList("");
    }
}

@Override
public void run() {
    while (true) {
        devices = query();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(WmiAccess.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

public ObservableList<String> getDevices() {
    return devices;
}

and i have an JavaFX fxml controller which adds that List to a ChoiceBox

@Override
public void initialize(URL url, ResourceBundle rb) {
    wmiAccess = new WmiAccess(
            "SELECT * FROM Win32_PnPEntity", "Name"
    );

    Thread wmiThread = new Thread(wmiAccess);

    wmiThread.start();

    choiceBox.setItems(wmiAccess.getDevices());

}

My problem now is: The ChoiceBox isn't updating its content automatically. How do i manage to update the content of the choiceBox to whatever value the 'devices' list holds?

Upvotes: 1

Views: 795

Answers (1)

James_D
James_D

Reputation: 209724

Two issues:

First, you are not updating the same list, you're creating a new one every time:

while (true) {
    devices = query();
    // ...
}

just assigns a new list to the variable devices on each iteration. Since the initialize() method in the controller just gets the reference once, when you update devices to a new list, it is no longer the list referenced from the controller.

You need something along the lines of

while (true) {
    devices.setAll(query);
    // ...
}

You need to make sure devices is properly initialized when that class is instantiated with devices = FXCollections.observableArrayList();.

At this point, you probably don't need query() to return an observable list any more, a regular list will do:

private List<String> query() {
    try {
        return getWMIValue(query, filename); // I'm guessing that returns a list...
    } catch (Exception e) {
        return Collections.emptyList();
    }
}

The second issue is that your non-terminating loop is running in a background thread. If devices is the list of items in a combo box, you can only update it on the FX Application Thread. So you need to do something like

while (true) {
    List<String> latestDevices = query();
    Platform.runLater(() -> devices.setAll(latestDevices));
    // ...
}

Upvotes: 1

Related Questions