-
Bug
-
Resolution: Fixed
-
P3
-
jfx11, jfx15, jfx16
-
x86_64
-
windows_10
-
Not verified
ADDITIONAL SYSTEM INFORMATION :
JDK-Version: 11.0.8
JavaFX-SDK-Version: 15.0.1
A DESCRIPTION OF THE PROBLEM :
Given there is a table with fixed size cells and multiple columns and multiple items. When some of the columns are removed after the tables is displayed, then the cells of the removed columns are not removed from the scene graph.
In JavaFX 8 the same problem also occurs when the columns are set invisible (TableColumn.setVisible(false)). Since then the problem has been partially resolved by removing the cells of invisible columns in TableRowSkinBase#updateCells(boolean). This method could be extended so that cells are removed, if the tableViewProperty of row and column are not equal.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
General Steps:
1. Create a TableView instance and add it to a window.
2. Set a fixed cell size (TableView#setFixedCellSize(double))
3. Add some columns and items to the table.
4. Display the window.
5. Remove some of the columns from the end of the column list. The combined width of the remaining columns must not exceed the visible area, otherwise the obsolete cells will not be visible.
Steps to run the attached example:
1. javac --module-path %PATH_TO_FX% --add-modules javafx.controls TestApp.java
2. java --module-path %PATH_TO_FX% --add-modules javafx.controls TestApp
3. Press the button labeled "Execute Test-Case"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TableCells of the removed columns are no longer visible.
ACTUAL -
TableCells of the removed columns stay in the table. Most of them are now empty but recognizable by the vertical lines.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TestApp extends
Application {
private static final int ITEM_COUNT = 100;
private static final int COLUMN_COUNT = 100;
private static final int TAIL_LENGTH = 90;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
TableView<String> table = new TableView<>();
table.getColumns().setAll(createColumns());
table.setItems(FXCollections.observableArrayList());
table.getItems().addAll(createItems());
table.setFixedCellSize(24);
Button buttonExecuteTestCase = new Button("Execute Test-Case");
buttonExecuteTestCase.setOnAction(event -> {
removeTailColumns(table);
});
ToolBar toolbar = new ToolBar(buttonExecuteTestCase);
BorderPane root = new BorderPane();
root.setTop(toolbar);
root.setCenter(table);
stage.setTitle("Hello World!");
stage.setScene(new Scene(root,
800,
500));
stage.show();
}
private static List<TableColumn<String, ?>> createColumns() {
List<TableColumn<String, ?>> columns = new ArrayList<>(COLUMN_COUNT);
for (int i = 1; i <= COLUMN_COUNT; i++) {
String name = "C"
+ i;
TableColumn<String, String> column = new TableColumn<>(name);
column.setCellValueFactory(cellDataFeatrues -> new SimpleStringProperty(name
+ " "
+ cellDataFeatrues.getValue()));
columns.add(column);
}
return columns;
}
private static List<String> createItems() {
List<String> items = new ArrayList<>(ITEM_COUNT);
for (int i = 1; i <= ITEM_COUNT; i++) {
items.add("R"
+ i);
}
return items;
}
private static void removeTailColumns(TableView<String> table) {
int from = table.getColumns().size()
- TAIL_LENGTH;
int to = table.getColumns().size();
table.getColumns().remove(from,
to);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
In JavaFX 8 the TableRowSkin can be extended as desribed above by the application developer. This is no longer possible in JavaFX 9+. No other workarounds known for more recent versions.
JDK-Version: 11.0.8
JavaFX-SDK-Version: 15.0.1
A DESCRIPTION OF THE PROBLEM :
Given there is a table with fixed size cells and multiple columns and multiple items. When some of the columns are removed after the tables is displayed, then the cells of the removed columns are not removed from the scene graph.
In JavaFX 8 the same problem also occurs when the columns are set invisible (TableColumn.setVisible(false)). Since then the problem has been partially resolved by removing the cells of invisible columns in TableRowSkinBase#updateCells(boolean). This method could be extended so that cells are removed, if the tableViewProperty of row and column are not equal.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
General Steps:
1. Create a TableView instance and add it to a window.
2. Set a fixed cell size (TableView#setFixedCellSize(double))
3. Add some columns and items to the table.
4. Display the window.
5. Remove some of the columns from the end of the column list. The combined width of the remaining columns must not exceed the visible area, otherwise the obsolete cells will not be visible.
Steps to run the attached example:
1. javac --module-path %PATH_TO_FX% --add-modules javafx.controls TestApp.java
2. java --module-path %PATH_TO_FX% --add-modules javafx.controls TestApp
3. Press the button labeled "Execute Test-Case"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TableCells of the removed columns are no longer visible.
ACTUAL -
TableCells of the removed columns stay in the table. Most of them are now empty but recognizable by the vertical lines.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TestApp extends
Application {
private static final int ITEM_COUNT = 100;
private static final int COLUMN_COUNT = 100;
private static final int TAIL_LENGTH = 90;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
TableView<String> table = new TableView<>();
table.getColumns().setAll(createColumns());
table.setItems(FXCollections.observableArrayList());
table.getItems().addAll(createItems());
table.setFixedCellSize(24);
Button buttonExecuteTestCase = new Button("Execute Test-Case");
buttonExecuteTestCase.setOnAction(event -> {
removeTailColumns(table);
});
ToolBar toolbar = new ToolBar(buttonExecuteTestCase);
BorderPane root = new BorderPane();
root.setTop(toolbar);
root.setCenter(table);
stage.setTitle("Hello World!");
stage.setScene(new Scene(root,
800,
500));
stage.show();
}
private static List<TableColumn<String, ?>> createColumns() {
List<TableColumn<String, ?>> columns = new ArrayList<>(COLUMN_COUNT);
for (int i = 1; i <= COLUMN_COUNT; i++) {
String name = "C"
+ i;
TableColumn<String, String> column = new TableColumn<>(name);
column.setCellValueFactory(cellDataFeatrues -> new SimpleStringProperty(name
+ " "
+ cellDataFeatrues.getValue()));
columns.add(column);
}
return columns;
}
private static List<String> createItems() {
List<String> items = new ArrayList<>(ITEM_COUNT);
for (int i = 1; i <= ITEM_COUNT; i++) {
items.add("R"
+ i);
}
return items;
}
private static void removeTailColumns(TableView<String> table) {
int from = table.getColumns().size()
- TAIL_LENGTH;
int to = table.getColumns().size();
table.getColumns().remove(from,
to);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
In JavaFX 8 the TableRowSkin can be extended as desribed above by the application developer. This is no longer possible in JavaFX 9+. No other workarounds known for more recent versions.