facon12
facon12

Reputation: 137

Issue with removing multiple rows at once from JavaFX TableView

I am trying to make a button that, when multiple rows in a TableView are selected, all of the selected rows are removed.

I am creating an observable list using getSelectedIndicies and it isn't working right.

If I select the first three rows, I have it print out the indicies as it removes them and it prints 0,1 and then it removes the first and third row, but the middle of the three rows is not removed.

delBtn.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent e) {
        ObservableList<Integer> index = 
            table.getSelectionModel().getSelectedIndices();

        for (int location: index) {
            System.out.println(location);
            data.remove(location);
        }

        table.getSelectionModel().clearSelection();
    }
});

Upvotes: 3

Views: 5744

Answers (5)

user1300214
user1300214

Reputation:

There is a way round this, using getSelectedIndices(), as the OP originally required. Here is the solution:

    ArrayList<Integer> list = new ArrayList<>(listView.getSelectionModel().getSelectedIndices());

    Comparator<Integer> comparator = Comparator.comparingInt(Integer::intValue);
    comparator = comparator.reversed();
    list.sort(comparator);

    for(Integer i : list) {

        listView.getItems().remove(i.intValue());
    }

This works because it sorts the indices in descending order, and so only removes the highest index first so that the indices of other items to be removed are not changed as a result of the removal.

Sometimes you can't use the getSelectedItems() and removeAll(...) functions because removeAll will remove all occurences of the referenced objects. What if your list contains multiple entries with the same referenced object, and you only want to remove one of those references? That's why you need to use the getSelectedIndices() function.

Upvotes: 0

Wingie
Wingie

Reputation: 121

I came across a similar issue using ListView (selectedView in my case) and also guessed items were removed by indices. So I gave up on using a loop looking like the following

selectedView.getSelectionModel().getSelectedItems().forEach(i -> selectedView.getItems().remove(i));

changing it to

selectedView.getItems().removeAll(selectedView.getSelectionModel().getSelectedItems());

which worked just fine. Hope this helps anybody.

Upvotes: 0

m4rlord
m4rlord

Reputation: 1272

You can use a for loop, it make a snapshoot of your table selection and iterate in it. For exmple:

@FXML
private void deleteButtonFired(ActionEvent actionEvent) throws InterruptedException {
    for(Object o : table.getSelectionModel().getSelectedItems()){
        table.getItems().remove(o);
    }
    table.getSelectionModel().clearSelection();
}

I hope they fix this bug.

Upvotes: 0

Rasha
Rasha

Reputation: 565

For some reason, this works:

 b.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent arg0) {
                    List items =  new ArrayList (treeTable.getSelectionModel().getSelectedItems());  
                    data.removeAll(items);
                    table.getSelectionModel().clearSelection();

                }
            });

I doubt that the internal implementation of the selectedItems list ( com.sun.javafx.collections.ObservableListWrapper ) might have some bug.

Edit Yes it's definitely a bug: https://javafx-jira.kenai.com/browse/RT-24367

Upvotes: 6

gontard
gontard

Reputation: 29540

Removing using index can't work since at each suppression the remaining indexes change.

You could remove the selectedItems :

delBtn.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent e) {
        data.removeAll(table.getSelectionModel().getSelectedItems());
        table.getSelectionModel().clearSelection();
    }
});

Upvotes: 4

Related Questions