JavaFX Обновление Vbox при добавлении содержимого
Есть окно с кнопкой "Добавить", по нажатию по которую открывается FileChooser. После выделения нескольких файлов в VBox добавляются "карточки" (экземпляры класса Controller) с описанием этих файлов. Проблема в том, что они добавляются все одновременно, а я хочу, чтобы они отображались в интерфейсе по мере обработки каждого файла (добавление в интерфейс в конце каждой итерации цикла).
@FXML
private void addHandle() throws IOException {
FileChooser fc = new FileChooser();
List<File> list = fc.showOpenMultipleDialog(stage);
DevFile devFile;
for(int i=0; i<list.size(); i++){
devFile = new DevFile(device, list.get(i), type);
Controller controller = createDevFileCard(devFile);
vbox.getChildren().add(controller.getRoot());
}
}
private Controller createDevFileCard(DevFile devFile) throws IOException {
loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/devFiles/editor_element.fxml"));
pane = (AnchorPane) loader.load();
controller = loader.getController();
controller.setElement(devFile);
return controller;
}
Пробовал запускать цикл в отдельном потоке и оттуда вызывать отрисовку Controller в потоке JavaFX через Platform.runlater(), но не получилось. Сначала создаются экземпляры класса Controller, затем они добавляются в vbox, и только затем все разом уже отображаются на экране. Аналогичная проблема возникла и с удалением "карточек" из VBox - удаляются все разом.
Ответы (1 шт):
Решение проблемы:
Создать отдельный поток, перенести логику в него, создать в нем элемент, который будет добавлен в vbox
Создать статичный метод, который возвращается в поток JavaFX, и в нем уже добавляет в vbox созданный элемент
//метод JavaFX класса private void addHandle(){ FileChooser fc = new FileChooser(); List<File> list = fc.showOpenMultipleDialog(stage); AddNewFiles thread = new AddNewFiles(list, this); thread.start(); } //поток, в котором реализована логика private class AddNewCard extends Thread{ Controller mainController; List<File> list; public AddNewFiles(List<File> list, Controller mainController){ this.list = list; this.mainController = mainController; } @Override public void run(){ //заполняем карточки контентом for(int i=0; i<list.size(); i++){ //какая-то логика //создаем элемент, который будем помещать в vbox ElementController elementController = createCard(); //вызываем статичный метод класса, содержащего vbox, передаем в него наш элемент Controller.addCardToVBox(mainController, elementController); } } } private static void addCardToVBox(Controller mainController, ElementController controller) { Thread thread = new Thread(new Runnable() { @Override public void run() { Runnable updater = new Runnable() { @Override public void run() { mainController.addToVbox(controller); } }; Platform.runLater(updater); } }); thread.setDaemon(true); thread.start(); } public void addToVbox(ElementController controller){ vbox.getChildren().add(controller.getRoot()); }