JavaFX — автоматическое обновление выбора.

У меня есть поток, который постоянно обновляет/создает список:

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;
}

и у меня есть контроллер JavaFX fxml, который добавляет этот список в 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());

}

Теперь моя проблема: ChoiceBox не обновляет свое содержимое автоматически. Как мне обновить содержимое selectionBox до любого значения, содержащегося в списке «устройств»?


person Dennis H.    schedule 02.02.2015    source источник


Ответы (1)


Две проблемы:

Во-первых, вы не обновляете один и тот же список, вы каждый раз создаете новый:

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

просто присваивает новый список переменной devices на каждой итерации. Поскольку метод initialize() в контроллере получает ссылку только один раз, когда вы обновляете devices до нового списка, это уже не тот список, на который ссылается контроллер.

Вам нужно что-то вроде

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

Вы должны убедиться, что devices правильно инициализирован, когда этот класс создается с помощью devices = FXCollections.observableArrayList();.

На данный момент вам, вероятно, больше не нужен query() для возврата наблюдаемого списка, подойдет обычный список:

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

Вторая проблема заключается в том, что ваш непрерывный цикл выполняется в фоновом потоке. Если devices — это список элементов в поле со списком, вы можете обновить его только в потоке приложения FX. Итак, вам нужно сделать что-то вроде

while (true) {
    List<String> latestDevices = query();
    Platform.runLater(() -> devices.setAll(latestDevices));
    // ...
}
person James_D    schedule 02.02.2015
comment
Большое вам спасибо, это сделало работу, но, к сожалению, привело меня прямо к другой проблеме. Может быть, это глупые вопросы, просто я впервые работаю со сложным графическим интерфейсом, извините заранее. Мой ChoiceBox теперь может отображать список всех устройств, но как только я выбрал одно, он напрямую сбрасывается, и ChoiceBox снова становится пустым, потому что поток обновляет список. Как я могу предотвратить удаление моего выбора? - person Dennis H.; 02.02.2015
comment
Это сделано .... удалось исправить это самостоятельно. Использовал ComboBox вместо ChoiceBox. Теперь все работает, как задумано. Спасибо еще раз - person Dennis H.; 02.02.2015