diff --git a/modules/controls/src/main/java/javafx/scene/control/TableCell.java b/modules/controls/src/main/java/javafx/scene/control/TableCell.java --- a/modules/controls/src/main/java/javafx/scene/control/TableCell.java +++ b/modules/controls/src/main/java/javafx/scene/control/TableCell.java @@ -560,6 +560,8 @@ private boolean isFirstRun = true; + private WeakReference oldRowItemRef; + /* * This is called when we think that the data within this TableCell may have * changed. You'll note that this is a private function - it is only called @@ -579,6 +581,9 @@ final boolean isEmpty = isEmpty(); final T oldValue = getItem(); + final TableRow tableRow = getTableRow(); + final S rowItem = tableRow == null ? null : tableRow.getItem(); + final boolean indexExceedsItemCount = index >= itemCount; // there is a whole heap of reasons why we should just punt... @@ -613,11 +618,19 @@ // unless the item has changed. if (oldIndex == index) { if (oldValue != null ? oldValue.equals(newValue) : newValue == null) { - return; + // RT-36670: we need to check the row item here to prevent + // the issue where the cell value and index doesn't change, + // but the backing row object does. + S oldRowItem = oldRowItemRef != null ? oldRowItemRef.get() : null; + if (oldRowItem != null && oldRowItem.equals(rowItem)) { + return; + } } } updateItem(newValue, false); } + + oldRowItemRef = new WeakReference<>(rowItem); if (currentObservableValue == null) { return; diff --git a/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java b/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java --- a/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java +++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java @@ -553,6 +553,8 @@ private boolean isFirstRun = true; + private WeakReference oldRowItemRef; + /* * This is called when we think that the data within this TreeTableCell may have * changed. You'll note that this is a private function - it is only called @@ -571,6 +573,9 @@ final boolean isEmpty = isEmpty(); final T oldValue = getItem(); + final TreeTableRow tableRow = getTreeTableRow(); + final S rowItem = tableRow == null ? null : tableRow.getItem(); + final boolean indexExceedsItemCount = index >= itemCount; // there is a whole heap of reasons why we should just punt... @@ -607,11 +612,19 @@ // unless the item has changed. if (oldIndex == index) { if (oldValue != null ? oldValue.equals(newValue) : newValue == null) { - return; + // RT-36670: we need to check the row item here to prevent + // the issue where the cell value and index doesn't change, + // but the backing row object does. + S oldRowItem = oldRowItemRef != null ? oldRowItemRef.get() : null; + if (oldRowItem != null && oldRowItem.equals(rowItem)) { + return; + } } } updateItem(newValue, false); } + + oldRowItemRef = new WeakReference<>(rowItem); if (currentObservableValue == null) { return; diff --git a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java @@ -3089,7 +3089,6 @@ assertEquals(1, TableColumnHeaderRetriever.getSortPos(emailColHeader)); } - @Ignore("Test written before fix was available.") @Test public void test_rt_36670() { final ObservableList data = FXCollections.observableArrayList( new Person("Jacob", "Smith", "jacob.smith@example.com", true),