-
Bug
-
Resolution: Won't Fix
-
P3
-
8u102
FULL PRODUCT VERSION :
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows 10 x64
A DESCRIPTION OF THE PROBLEM :
Styles on nodes contained by tablecells do not update properly when table columns are shown/hidden.
For example, if you have a table with a cell factory which sets the graphic to some node, updating that node's style in the TableCell's update method fails when you show or hide the column containing that table cell.
Setting the style on the tablecell itself doesn't have this problem.
REGRESSION. Last worked in version 8u92
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Press show/hide twice.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The cyan and magenta column should alternate between cyan and magenta.
ACTUAL -
The background colours in the column broke permanently. Scrolling up and down didn't fix the colours. The text within the cells updates correctly when you scroll.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package tabletestproject;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author Jeremy
*/
public class TableCSS extends Application {
boolean toggle = false;
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
final ObservableList<ObjectRow> data = FXCollections.observableArrayList();
int numColumns = 3;
int numRows = 1000;
for (int i = 0; i < numRows; i++) {
String text[] = new String[numColumns];
String paneStyle[] = new String[numColumns];
String cellStyle[] = new String[numColumns];
for (int j = 0; j < numColumns; j++) {
text[j] = "Row " + i + " Col " + j;
if (j % 2 == 0) {
if (i % 2 == 0) {
paneStyle[j] = "-fx-background-color:lightgreen";
cellStyle[j] = "";//"-fx-border-color: red";
} else {
paneStyle[j] = "-fx-background-color:red";
cellStyle[j] = "";//"-fx-border-color: green";
}
} else {
if (i % 2 == 0) {
paneStyle[j] = "-fx-background-color:cyan";
cellStyle[j] = "";//"-fx-border-color: magenta";
} else {
paneStyle[j] = "-fx-background-color:magenta";
cellStyle[j] = "";//"-fx-border-color: cyan";
}
}
}
data.add(new ObjectRow(text, cellStyle, paneStyle));
}
TableView<ObjectRow> table = new TableView<>();
for (int i = 0; i < numColumns; i++) {
TableColumn<ObjectRow, ObjectCell> col = new TableColumn("Col " + (i + 1));
col.setMinWidth(100);
final int j = i;
col.setCellValueFactory(row -> {
return new SimpleObjectProperty<>(row.getValue().labels[j]);
});
col.setCellFactory(new Callback<TableColumn<ObjectRow, ObjectCell>, TableCell<ObjectRow, ObjectCell>>() {
@Override
public TableCell<ObjectRow, ObjectCell> call(TableColumn<ObjectRow, ObjectCell> param) {
return new TableCell<ObjectRow, ObjectCell>() {
HBox vbox = new HBox();
Label lab = new Label();
{
this.setGraphic(vbox);
vbox.getChildren().add(lab);
}
@Override
protected void updateItem(ObjectCell item, boolean empty) {
if (item == null || empty) {
this.setGraphic(null);
this.setText(null);
} else {
lab.setText(item.text);
vbox.setStyle(item.paneStyle);
this.setStyle(item.cellStyle);
this.setGraphic(vbox);
}
super.updateItem(item, empty);
}
};
}
});
table.getColumns().add(col);
}
table.setItems(data);
Button b2 = new Button("Show/Hide");
b2.setOnAction((e) -> {
toggle = !toggle;
table.getColumns().get(0).setVisible(toggle);
table.getColumns().get(1).setVisible(!toggle);
});
root.getChildren().add(new VBox(b2, table));
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class ObjectRow {
public ObjectCell[] labels;
public ObjectRow(String text[], String cellStyle[], String paneStyle[]) {
labels = new ObjectCell[text.length];
for (int i = 0; i < text.length; i++) {
labels[i] = new ObjectCell(text[i], cellStyle[i], paneStyle[i]);
}
}
}
public class ObjectCell {
public final String text;
public final String cellStyle;
public final String paneStyle;
public ObjectCell(String text, String cellStyle, String paneStyle) {
this.text = text;
this.cellStyle = cellStyle;
this.paneStyle = paneStyle;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If you can set a new style on the tablecell itself when you change the styles of the children nodes in the graphic, then the children's styles will update as well. It must be a new style however.
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows 10 x64
A DESCRIPTION OF THE PROBLEM :
Styles on nodes contained by tablecells do not update properly when table columns are shown/hidden.
For example, if you have a table with a cell factory which sets the graphic to some node, updating that node's style in the TableCell's update method fails when you show or hide the column containing that table cell.
Setting the style on the tablecell itself doesn't have this problem.
REGRESSION. Last worked in version 8u92
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Press show/hide twice.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The cyan and magenta column should alternate between cyan and magenta.
ACTUAL -
The background colours in the column broke permanently. Scrolling up and down didn't fix the colours. The text within the cells updates correctly when you scroll.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package tabletestproject;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author Jeremy
*/
public class TableCSS extends Application {
boolean toggle = false;
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
final ObservableList<ObjectRow> data = FXCollections.observableArrayList();
int numColumns = 3;
int numRows = 1000;
for (int i = 0; i < numRows; i++) {
String text[] = new String[numColumns];
String paneStyle[] = new String[numColumns];
String cellStyle[] = new String[numColumns];
for (int j = 0; j < numColumns; j++) {
text[j] = "Row " + i + " Col " + j;
if (j % 2 == 0) {
if (i % 2 == 0) {
paneStyle[j] = "-fx-background-color:lightgreen";
cellStyle[j] = "";//"-fx-border-color: red";
} else {
paneStyle[j] = "-fx-background-color:red";
cellStyle[j] = "";//"-fx-border-color: green";
}
} else {
if (i % 2 == 0) {
paneStyle[j] = "-fx-background-color:cyan";
cellStyle[j] = "";//"-fx-border-color: magenta";
} else {
paneStyle[j] = "-fx-background-color:magenta";
cellStyle[j] = "";//"-fx-border-color: cyan";
}
}
}
data.add(new ObjectRow(text, cellStyle, paneStyle));
}
TableView<ObjectRow> table = new TableView<>();
for (int i = 0; i < numColumns; i++) {
TableColumn<ObjectRow, ObjectCell> col = new TableColumn("Col " + (i + 1));
col.setMinWidth(100);
final int j = i;
col.setCellValueFactory(row -> {
return new SimpleObjectProperty<>(row.getValue().labels[j]);
});
col.setCellFactory(new Callback<TableColumn<ObjectRow, ObjectCell>, TableCell<ObjectRow, ObjectCell>>() {
@Override
public TableCell<ObjectRow, ObjectCell> call(TableColumn<ObjectRow, ObjectCell> param) {
return new TableCell<ObjectRow, ObjectCell>() {
HBox vbox = new HBox();
Label lab = new Label();
{
this.setGraphic(vbox);
vbox.getChildren().add(lab);
}
@Override
protected void updateItem(ObjectCell item, boolean empty) {
if (item == null || empty) {
this.setGraphic(null);
this.setText(null);
} else {
lab.setText(item.text);
vbox.setStyle(item.paneStyle);
this.setStyle(item.cellStyle);
this.setGraphic(vbox);
}
super.updateItem(item, empty);
}
};
}
});
table.getColumns().add(col);
}
table.setItems(data);
Button b2 = new Button("Show/Hide");
b2.setOnAction((e) -> {
toggle = !toggle;
table.getColumns().get(0).setVisible(toggle);
table.getColumns().get(1).setVisible(!toggle);
});
root.getChildren().add(new VBox(b2, table));
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class ObjectRow {
public ObjectCell[] labels;
public ObjectRow(String text[], String cellStyle[], String paneStyle[]) {
labels = new ObjectCell[text.length];
for (int i = 0; i < text.length; i++) {
labels[i] = new ObjectCell(text[i], cellStyle[i], paneStyle[i]);
}
}
}
public class ObjectCell {
public final String text;
public final String cellStyle;
public final String paneStyle;
public ObjectCell(String text, String cellStyle, String paneStyle) {
this.text = text;
this.cellStyle = cellStyle;
this.paneStyle = paneStyle;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If you can set a new style on the tablecell itself when you change the styles of the children nodes in the graphic, then the children's styles will update as well. It must be a new style however.