-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
jfx13
-
x86_64
-
windows_10
ADDITIONAL SYSTEM INFORMATION :
JavaFX 13
A DESCRIPTION OF THE PROBLEM :
When a TableView column is frequently invalidated, while it's contents are changing, it will result a layout that attempts to recreate a row's cells that will always fail with a null pointer exception.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Frequently update a table's contents while another binding invalidates the column. See attached test case.
ACTUAL -
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.controls/javafx.scene.control.skin.TableCellSkin.tableColumnProperty(TableCellSkin.java:97)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.getTableColumn(TableCellSkinBase.java:123)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.dispose(TableCellSkinBase.java:136)
at javafx.controls/javafx.scene.control.skin.TableCellSkin.dispose(TableCellSkin.java:88)
at javafx.controls/javafx.scene.control.Control$2.invalidated(Control.java:267)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.graphics/javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:250)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:233)
at javafx.controls/javafx.scene.control.Control.setSkin(Control.java:230)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:715)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:505)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.checkState(TableRowSkinBase.java:649)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.computePrefHeight(TableRowSkinBase.java:588)
at javafx.controls/javafx.scene.control.Control.computePrefHeight(Control.java:570)
at javafx.graphics/javafx.scene.Parent.prefHeight(Parent.java:1039)
at javafx.graphics/javafx.scene.layout.Region.prefHeight(Region.java:1559)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.resizeCell(VirtualFlow.java:1923)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:2030)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1250)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1206)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2482)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)
---------- BEGIN SOURCE ----------
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
import org.testfx.util.WaitForAsyncUtils;
import java.util.List;
public class TableViewBug extends ApplicationTest {
private ObjectProperty<List<Item>> data;
private TableView<Item> table;
@Override
public void start(Stage stage) {
initialize();
stage.setScene(new Scene(table, 500, 500));
stage.show();
}
private void initialize() {
data = new SimpleObjectProperty<>();
table = new TableView<>();
TableColumn<Item, String> dataCol = new TableColumn<>("Data");
dataCol.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().data.toString()));
TableColumn<Item, String> labelCol = new TableColumn<>("Label");
labelCol.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getLabel()));
table.getColumns().add(dataCol);
table.getColumns().add(labelCol);
dataCol.prefWidthProperty().bind(table.widthProperty().multiply(.5));
labelCol.prefWidthProperty().bind(table.widthProperty().multiply(.5));
data.addListener((prop, oldVal, newVal) -> table.setItems(FXCollections.observableList(data.get())));
// This binding is what causes the trouble, even if the value doesn't change whenever it's evaluated it invalidates the TableViewRows
labelCol.visibleProperty().bind(Bindings.createBooleanBinding(() -> true, data));
}
@Test
void bug() throws Throwable {
WaitForAsyncUtils.asyncFx(() -> data.set(List.of(new Item(1, "one"))));
// Number of iterations seems to be related to the delay between data updates (sleep amount below)
for (int i = 0; i < 200; i++) {
Thread.sleep(20); // Delay simulates work being done to produce data
Platform.runLater(() ->
data.set(List.of(new Item(2, "two"))));
WaitForAsyncUtils.checkException(); // THis is to end the test after the first exception shows up, if not it'll keep going and hang with more
}
}
private static class Item {
private final Integer data;
private final String label;
private Item(Integer data, String label) {
this.data = data;
this.label = label;
}
public Integer getData() {
return data;
}
public String getLabel() {
return label;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid invalidating the column.
FREQUENCY : always
JavaFX 13
A DESCRIPTION OF THE PROBLEM :
When a TableView column is frequently invalidated, while it's contents are changing, it will result a layout that attempts to recreate a row's cells that will always fail with a null pointer exception.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Frequently update a table's contents while another binding invalidates the column. See attached test case.
ACTUAL -
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.controls/javafx.scene.control.skin.TableCellSkin.tableColumnProperty(TableCellSkin.java:97)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.getTableColumn(TableCellSkinBase.java:123)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.dispose(TableCellSkinBase.java:136)
at javafx.controls/javafx.scene.control.skin.TableCellSkin.dispose(TableCellSkin.java:88)
at javafx.controls/javafx.scene.control.Control$2.invalidated(Control.java:267)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.graphics/javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:250)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:233)
at javafx.controls/javafx.scene.control.Control.setSkin(Control.java:230)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:715)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:505)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.checkState(TableRowSkinBase.java:649)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.computePrefHeight(TableRowSkinBase.java:588)
at javafx.controls/javafx.scene.control.Control.computePrefHeight(Control.java:570)
at javafx.graphics/javafx.scene.Parent.prefHeight(Parent.java:1039)
at javafx.graphics/javafx.scene.layout.Region.prefHeight(Region.java:1559)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.resizeCell(VirtualFlow.java:1923)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:2030)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1250)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1206)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1213)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2482)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)
---------- BEGIN SOURCE ----------
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
import org.testfx.util.WaitForAsyncUtils;
import java.util.List;
public class TableViewBug extends ApplicationTest {
private ObjectProperty<List<Item>> data;
private TableView<Item> table;
@Override
public void start(Stage stage) {
initialize();
stage.setScene(new Scene(table, 500, 500));
stage.show();
}
private void initialize() {
data = new SimpleObjectProperty<>();
table = new TableView<>();
TableColumn<Item, String> dataCol = new TableColumn<>("Data");
dataCol.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().data.toString()));
TableColumn<Item, String> labelCol = new TableColumn<>("Label");
labelCol.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getLabel()));
table.getColumns().add(dataCol);
table.getColumns().add(labelCol);
dataCol.prefWidthProperty().bind(table.widthProperty().multiply(.5));
labelCol.prefWidthProperty().bind(table.widthProperty().multiply(.5));
data.addListener((prop, oldVal, newVal) -> table.setItems(FXCollections.observableList(data.get())));
// This binding is what causes the trouble, even if the value doesn't change whenever it's evaluated it invalidates the TableViewRows
labelCol.visibleProperty().bind(Bindings.createBooleanBinding(() -> true, data));
}
@Test
void bug() throws Throwable {
WaitForAsyncUtils.asyncFx(() -> data.set(List.of(new Item(1, "one"))));
// Number of iterations seems to be related to the delay between data updates (sleep amount below)
for (int i = 0; i < 200; i++) {
Thread.sleep(20); // Delay simulates work being done to produce data
Platform.runLater(() ->
data.set(List.of(new Item(2, "two"))));
WaitForAsyncUtils.checkException(); // THis is to end the test after the first exception shows up, if not it'll keep going and hang with more
}
}
private static class Item {
private final Integer data;
private final String label;
private Item(Integer data, String label) {
this.data = data;
this.label = label;
}
public Integer getData() {
return data;
}
public String getLabel() {
return label;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid invalidating the column.
FREQUENCY : always
- duplicates
-
JDK-8243940 NullPointerException in TableCellSkin when automatically resizing cells
-
- Open
-
- relates to
-
JDK-8243940 NullPointerException in TableCellSkin when automatically resizing cells
-
- Open
-