Reputation: 1432
I have the following piece of code to set background Color of a TableRow
,
column.setCellFactory((TableColumn<Model, Integer> p) -> {
ComboBoxTableCell cell = new ComboBoxTableCell(FXCollections.observableArrayList(0, 1)) {
@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
if(Integer.valueOf(item.toString()) == 1){
getTableRow().setStyle("-fx-background-color: khaki;");
}else if(Integer.valueOf(item.toString()) == 0){
getTableRow().setStyle(null);
}
}
}
};
return cell;
});
The problem is when i select the row with background set to some color, the default blue color which indicates selection goes behind. (like below)
How can i retain the default selection color?
Upvotes: 0
Views: 572
Reputation: 82461
Inline style has higher priority than CSS stylesheets. Therefore the background for selected rows is also overridden. The way the background is constructed requires you to use specify -fx-control-inner-background-alt
and -fx-control-inner-background
instead.
[...].setStyle("-fx-control-inner-background: khaki; -fx-control-inner-background-alt: khaki;")
However there's an issue that's much worse:
You set the style from the TableCell
s. Since TableView
is responsible for assigning the items to the cells, the order this is done is an implementation detail resulting in arbitrary outcomes, if you use the cell type in different columns. Even if you use these cells in only one column, you never handle the case where the cells become empty, so even empty cells may still contain the new color.
Row styling belongs to the table rows.
Also you get the most flexibility, if you use a PseudoClass
and a CSS stylesheet.
E.g.
final PseudoClass one = PseudoClass.getPseudoClass("one");
tableView.setRowFactory(t -> new TableRow<Model>() {
private ChangeListener<Integer> listener = (o, oldValue, newValue) -> {
pseudoClassStateChanged(one, newValue == 1);
};
@Override
protected void updateItem(Model model, boolean empty) {
if (getItem() != null) {
getItem().myValueProperty().removeListener(listener);
}
super(model, empty);
if (empty || model == null) {
listener.changed(null, 0, -1);
} else {
model.myValueProperty().addListener(listener);
listener.changed(null, 0, model.getMyValue());
}
}
});
CSS stylesheet
.table-row-cell:one {
-fx-control-inner-background: khaki;
-fx-control-inner-background-alt: khaki;
}
Furthermore you should use type parameters to avoid converting to your item from Integer
to String
and back to Integer
(which should be replaced by a cast, if it needs to be done this way. In this case it's better not to use raw types.).
final ObservableList<Integer> values = FXCollections.observableArrayList(0, 1);
column.setCellFactory((TableColumn<Model, Integer> p) -> {
ComboBoxTableCell<Model, Integer> cell = new ComboBoxTableCell<Model, Integer>(values) {
@Override
protected void updateItem(Integer item, boolean empty) {
...
}
};
return cell;
});
Upvotes: 2