Ссылка javafx / привязка элементов treeview к observablelist

Я пытаюсь найти простой способ связать В виде дерева типа Download с ObservableList того же типа.

MainController.java

public class MainController {

    private ObservableList<Download> downloads = FXCollections.observableArrayList();
    @FXML private TreeView<Download> $TreeDownloads;

    @FXML
    public void initialize() {
        $TreeDownloads.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        $TreeDownloads.setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
        $TreeDownloads.setShowRoot(false);

        downloads.addListener(new ListChangeListener<Download>() {
            @Override
            public void onChanged(Change<? extends Download> c) {
                if (c.wasAdded()) {
                    addDownloads(c.getAddedSubList());
                }
                if (c.wasRemoved()) {
                    //
                }
            }
        });
        downloads.add(new Download("3847"));
        downloads.add(new Download("3567"));
        downloads.add(new Download("2357"));
    }

    private void addDownloads(List<? extends Download> downloads) {
        downloads.forEach(download -> {
            TreeItem<Download> treeItem = new TreeItem<>(download);
            $TreeDownloads.getRoot().getChildren().add(treeItem);
            new Thread(download::start).start();
        });
    }

    private void removeDownloads(List<? extends Download> downloads) {
        // remove treeitems from the treeview that hold these downloads
    }
}

Download.java

public class Download {

    private DoubleProperty progress = new SimpleDoubleProperty(0D);
    private StringProperty id = new SimpleStringProperty("");

    public Download(String id) {
        this.id.set(id);
    }

    public void start() {
        while (progress.getValue() < 1) {
            try {
                Thread.sleep(1000);
                progress.add(0.1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }      

    @Override
    public String toString() {
        return id.getValue();
    }
}

Как реализовать механизм Удалить с помощью механизма Объект (Скачать) и есть ли более простой способ привязать элементы наблюдаемого списка к древовидной структуре?

2
0
1 832
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Все еще не совсем уверен, в чем именно проблема, все довольно просто:

Во-первых, ваша реализация прослушивателя изменений списка неверна, она должна продвигать subChanges перед доступом к своему состоянию (вы выполнили свой опубликованный код или нет;)

downloads.addListener(new ListChangeListener<Download>() {
    @Override
    public void onChanged(Change<? extends Download> c) {
        // this while was missing
        while (c.next()) {
            if (c.wasAdded()) {
                addDownloads(c.getAddedSubList());
            }
            if (c.wasRemoved()) {
                // accessing the list of removed elements is .. plain standard api 
                removeDownloads(c.getRemoved());
            }

        }
    }
});

Теперь реализуйте удаление соответствующих treeItems:

private void removeDownloads(List<? extends Download> downloads) {
    // remove treeitems from the treeview that hold these downloads
    List<TreeItem<Download>> treeItemsToRemove = treeDownloads.getRoot().getChildren().stream()
            .filter(treeItem -> downloads.contains(treeItem.getValue()))
            .collect(Collectors.toList());
    treeDownloads.getRoot().getChildren().removeAll(treeItemsToRemove);
}

В сторону:

  • В соглашениях об именах java для членов используются строчные буквы: treeDownloads (не $ TreeDownloads)
  • "проверяемый" в MCVE подразумевает возможность запуска как есть: плакат должен быть первым, кто это подтвердит;) ваше не было связано с неправильной реализацией слушателя
  • «минимальный» в MCVE означает исключение всего, что не нужно: f.i. вызов кода потоковой передачи - который в вашем первом фрагменте особенно отвлекал, потому что нарушение правила потоковой передачи fx - довольно распространенная ошибка

Понятно, спасибо за решение и советы;) Что касается того, как я назвал переменную treeview, это всего лишь соглашение для моей базы кода, все элементы управления fxml ui начинаются с $ ControlName. Я обнаружил, что это упрощает отладку

DarkMental 11.08.2018 16:28

@DarkMental достаточно честно - хотя вы могли бы подумать о том, чтобы не использовать такое частное соглашение в публичном коде :)

kleopatra 11.08.2018 16:41

В этом есть смысл, с этого момента я буду этим заниматься, спасибо за совет :)

DarkMental 11.08.2018 16:48

Другие вопросы по теме