I have problem with refresh rows styles in JavaFX TableView.
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) Server VM (build 25.51-b03, mixed mode)
Logic:
How to reload styles for rows?
My code snippet:
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class RowFactoryAndOptimisationDemo extends Application {
VBox root;
public ObservableList<RFDDomain> data = FXCollections.observableArrayList();
public TableView<RFDDomain> tableView = new TableView<RFDDomain>();
@Override
public void start(Stage stage) throws Exception {
root = new VBox();
root.autosize();
Scene scene = new Scene(root, Color.LINEN);
stage.setTitle("Row Factory Demo");
stage.setWidth(500);
stage.setHeight(300);
stage.setScene(scene);
stage.show();
configureTable();
}
public static void main(String[] args) {
Application.launch(args);
}
private void recheck_table() {
tableView.setRowFactory(new Callback<TableView<RFDDomain>, TableRow<RFDDomain>>() {
@Override
public TableRow<RFDDomain> call(TableView<RFDDomain> paramP) {
return new TableRow<RFDDomain>() {
@Override
protected void updateItem(RFDDomain paramT, boolean paramBoolean) {
super.updateItem(paramT, paramBoolean);
if (!isEmpty()) {
String style = "-fx-control-inner-background: #007F0E;"
+ "-fx-control-inner-background-alt: #007F0E;";
setStyle(style);
}
}
};
}
});
}
@SuppressWarnings("unchecked")
private void configureTable() {
int id =1;
for (int i = 1; i <= 1; i++) {
data.add(new RFDDomain(id++,"First Row", "This is for check.", 1));
data.add(new RFDDomain(id++,"Second Row", null, 2));
data.add(new RFDDomain(id++,"Third Row", "This is for check.", 3));
data.add(new RFDDomain(id++,"Fourth Row", "dil", 4));
}
tableView.setItems(data);
recheck_table();
TableColumn<RFDDomain, Integer> column0 = new TableColumn<RFDDomain, Integer>("Id");
column0.setCellValueFactory(new PropertyValueFactory<RFDDomain, Integer>("id"));
TableColumn<RFDDomain, String> column1 = new TableColumn<RFDDomain, String>("Title");
column1.setCellValueFactory(new PropertyValueFactory<RFDDomain, String>("name"));
TableColumn<RFDDomain, String> column2 = new TableColumn<RFDDomain, String>("Description");
column2.setCellValueFactory(new PropertyValueFactory<RFDDomain, String>("description"));
TableColumn<RFDDomain, Number> column3 = new TableColumn<RFDDomain, Number>("Status");
column3.setPrefWidth(55);
column3.setCellValueFactory(new PropertyValueFactory<RFDDomain, Number>("status"));
TableColumn<RFDDomain, String> column4 = new TableColumn<RFDDomain, String>("Action");
column4.setCellValueFactory(new PropertyValueFactory<RFDDomain, String>("name"));
tableView.getColumns().addAll(column0, column1, column2, column3, column4);
this.root.getChildren().add(tableView);
Button button1 = new Button("Load new Data");
button1.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
data.clear();
data.removeAll(data);
data.add(new RFDDomain(1,"First Row", "This is for check.", 1));
data.add(new RFDDomain(2,"Second Row", null, 2));
tableView.setItems(data);
recheck_table();
}
});
this.root.getChildren().add(button1);
}
/**
* Domain Model for this demo.
*/
public class RFDDomain {
private SimpleIntegerProperty id = new SimpleIntegerProperty();
private SimpleStringProperty name = new SimpleStringProperty();
private SimpleStringProperty description = new SimpleStringProperty();
private SimpleIntegerProperty status = new SimpleIntegerProperty();
public RFDDomain(int id,String name, String desc, int status) {
this.id.set(id);
this.name.set(name);
this.description.set(desc);
this.status.set(status);
}
public int getId() {
return id.get();
}
public SimpleIntegerProperty idProperty() {
return id;
}
public String getDescription() {
return description.get();
}
public SimpleStringProperty descriptionProperty() {
return description;
}
public String getName() {
return name.get();
}
public SimpleStringProperty nameProperty() {
return name;
}
public int getStatus() {
return status.get();
}
public SimpleIntegerProperty statusProperty() {
return status;
}
}
}
Try tableView.refresh()
. It's available in JavaFX since Java 8u60.
Probably no longer relevant, but simply add
else { setStyle(null) }
to the updateItem
method in your custom factory - what's happening is that only as many cells are created as are absolutely required to show on the screen (prevents creating unnecessarily many UI elements). These cells are re-used when you scroll through the table by their updateItem
method. Sometimes (in your case), an existing cell will be updated with null
to indicate the cell should be empty. You haven't implemented this case, but you should, and you should clear the cell's style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With