Примечание: Это решение делает некоторые предположения относительно вашей реализации, поскольку вы не предоставили Минимальный, Полный и Проверяемый пример вашего кода.
Вам не нужно использовать привязку для этого. ComboBox
использует ObservableList
для заполнения своих пунктов. Ключевое слово здесь наблюдаемое . Это означает, что при изменении базового List
ComboBox
будет «видеть» изменения и автоматически обновлять отображаемые элементы.
Вы инициализируете ComboBox
методом setItems()
, передавая ему ObservableList
в качестве параметра:
comboBox.setItems(programList);
Оттуда, каждый раз, когда programList
обновляется (элементы добавляются, удаляются и т. Д.), ComboBox
будет отражать изменения без какого-либо дополнительного кода, необходимого от вас.
Просмотрите следующий полный пример:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class ComboBoxListenerExample extends Application {
// This is our ObservableList that will hold our ComboBox items
private ObservableList<String> items = FXCollections.observableArrayList();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple interface
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// Simple ComboBox
ComboBox<String> comboBox = new ComboBox<>();
// Let's "permanently" set our ComboBox items to the "items" ObservableList. This causes the
// ComboBox to "observe" the list for changes
comboBox.setItems(items);
// Create a button that will reload data from our "database"
Button button = new Button("Refresh Data");
// The items.setAll()` method replaces all items in the list with our new list of items
button.setOnAction(event -> items.setAll(reloadDatabase()));
root.getChildren().addAll(comboBox, button);
// Show the Stage
primaryStage.setWidth(300);
primaryStage.setHeight(300);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
// Sample method to simulate reloading the database information
private List<String> reloadDatabase() {
List<String> items = new ArrayList<>();
for (int i = 0; i < 5; i++) {
items.add(getRandomWord());
}
return items;
}
// Just a helper method specific for this example; it simply returns a random word.
// This is used to simulate loading new data from the database
private String getRandomWord() {
List<String> words = Arrays.asList("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Red", "Blue", "Green", "Yellow", "Left", "Right", "Top", "Bottom");
Random random = new Random();
return words.get(random.nextInt(words.size()));
}
}
После запуска примера ComboBox
пуст. Каждый раз, когда вы нажимаете кнопку «Обновить данные», базовые значения ObservableList
, items
обновляются новым списком случайных элементов; ComboBox
изменяется, чтобы немедленно отразить эти изменения.
Нет в потоке приложения JavaFX:
А как насчет этого сообщения об ошибке? В StackOverflow есть много вопросов и ответов, которые уже решают эту проблему, но вот краткое объяснение:
Я предполагаю, что вы загружаете данные из базы данных в фоновом потоке и , что хорошо! Однако вы не можете вносить какие-либо изменения или обновления в пользовательский интерфейс из этого потока. Все обновления пользовательского интерфейса должны выполняться в потоке приложений JavaFX.
Это очень просто сделать. Когда вы обновляете List
при вызове метода базы данных, оберните это обновление в Platform.runLater()
вызов:
Platform.runLater(() -> programList.setAll(yourNewList));
Запланирует обновление списка в потоке приложений JFX. Проблема решена!