controlsfx / controlsfx/controlsfx

GridView does not unregister listeners of GridViewSkin if items-list is changed with setItems()

Open
#1,065 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
1.7k
Forks
300
Avg merge
16d 17h
Merged PRs (30d)
1

Description

**[Original report](https://bitbucket.org/controlsfx/controlsfx/issue/874) by acuriousbison NA (Bitbucket: [acuriousbison](https://bitbucket.org/acuriousbison), GitHub: Unknown).**

----------------------------------------

If the items-list of a GridView is changed with setItems() the GridViewSkin does not remove its ListChangeListener("gridViewItemsListener") from the old items when updateGridViewItems() is called. If the old items-list changes afterwards, the listener is still triggered and calls updateRowCount() even though the old items-list is no longer associated with the GridView.

Sample code:

```
#!java

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.GridView;

public class GridViewListenerIssue extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList listA = FXCollections.observableArrayList();
listA.add("foo");
ObservableList listB = FXCollections.observableArrayList();
listB.add("bar");

GridView grid = new GridView<>();
grid.setItems(listA);

VBox root = new VBox(grid);
root.setPrefSize(400, 400);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();

grid.setItems(listB);

// Changes to the old list will still trigger the GridViewSkin.gridViewItemsListener
listA.add("foo");
}
}

```

Looking at ListViewSkin, I suspect that the listener should be removed from the old items-list when updateGridViewItems() is called:

```
#!java
public class GridViewSkin {

public void updateGridViewItems() {
if (getSkinnable().getItems() != null) {
getSkinnable().getItems().removeListener(weakGridViewItemsListener);
}

if (getSkinnable().getItems() != null) {
getSkinnable().getItems().addListener(weakGridViewItemsListener);
}

updateRowCount();
flow.recreateCells();
getSkinnable().requestLayout();
}

}

public class ListViewSkin {

public void updateListViewItems() {
if (listViewItems != null) {
listViewItems.removeListener(weakListViewItemsListener);
}

this.listViewItems = getSkinnable().getItems();

if (listViewItems != null) {
listViewItems.addListener(weakListViewItemsListener);
}

rowCountDirty = true;
getSkinnable().requestLayout();
}

}
```

The described issue can also cause IndexOutOfBoundsException when using a FilteredList as items: The old FilteredList triggers the listener in GridViewSkin and when the GridCells try to update their index/item the indices of the (not yet changed) new FilteredList are being used.

Sample Code:

```
#!java

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.GridView;

public class GridViewListenerIssue2 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList source = FXCollections.observableArrayList();
source.add("bar");
source.add("bar");
source.add("foo");
source.add("foo");

FilteredList filteredListFoo = source.filtered(s -> s.startsWith("foo"));
FilteredList filteredListBar = source.filtered(s -> s.startsWith("bar"));

GridView grid = new GridView<>();
grid.setItems(filteredListFoo);

VBox root = new VBox(grid);
root.setPrefSize(400, 400);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();

grid.setItems(filteredListBar);
source.setAll("bar");
}
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.