Mark Price
Mark Price

Reputation: 85

JavaFX can not clear items from listview

I'm using a ListView in my project and wanted to add a context menu to each list item so that each can be removed individually. When using the following code this appears to work just fine:

postList.setCellFactory(lv -> {
            ListCell<Result> cell = new ListCell<>();
            ContextMenu contextMenu = new ContextMenu();

            StringBinding stringBinding = new StringBinding() {
                {
                    super.bind(cell.itemProperty().asString());
                }

                @Override
                protected String computeValue() {
                    if (cell.itemProperty().getValue() == null) {
                        return "";
                    }
                    return cell.itemProperty().getValue().getTitle();
                }
            };
            cell.textProperty().bind(stringBinding);

            MenuItem deleteItem = new MenuItem();
            deleteItem.textProperty().bind(Bindings.format("Delete item"));
            deleteItem.setOnAction(event -> postList.getItems().remove(cell.getItem()));
            contextMenu.getItems().addAll(openPermalink, openSubreddit, openURL, deleteItem);

            cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
                if (isNowEmpty) {
                    cell.setContextMenu(null);
                } else {
                    cell.setContextMenu(contextMenu);
                }
            });

            return cell;
        });

However, after clearing the post list - although the items appear to be removed - when another is added all of the removed items re-appear and the item to be added is not displayed.

Any items what could be causing this? It only happens when I set the cell factory and is fine otherwise.

I recorded a small gif to help better explain the issue: Adding and clearing items

Thank you!

Edit: It appears that the issue is mainly to do with this segment

StringBinding stringBinding = new StringBinding() {
                {
                    super.bind(cell.itemProperty().asString());
                }

                @Override
                protected String computeValue() {
                    if (cell.itemProperty().getValue() == null) {
                        return "";
                    }
                    return cell.itemProperty().getValue().getTitle();
                }
            };

As is seems that even though the items are there they have an empty display title

Upvotes: 1

Views: 1267

Answers (1)

Sergey Grinev
Sergey Grinev

Reputation: 34508

If you use ListCell.updateItem() workflow instead of the StringBinding it should work:

        ListCell< Result > cell = new ListCell< Result >() {
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null) {
                    setText(item.getValue());
                } else {
                    setText("");
                }
            }
        };

Your binding workflow seems to create an unnecessary dependency which blocks deletion.


P.S.: why do you use binding for static text in deleteItem? Just assign the value directly:

        MenuItem deleteItem = new MenuItem();
        deleteItem.setText("Delete item");

Upvotes: 2

Related Questions