Java FX - filling table rows in different colours - java

I updated my code to show how the whole class look like
Still I got some errors can you validate what I need to improve to have it working
Mainly the problem is with fillTableView() method
private TableCell fillTableView() {
clientColumn.setCellFactory(column -> {
return new TableCell<CarFx, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? "" : getItem().toString());
setGraphic(null);
TableRow<CarFx> currentRow = getTableRow();
if (!isEmpty()) {
if (item.equals("EMPTY EMPTY"))
currentRow.setStyle("-fx-background-color:green");
else
currentRow.setStyle("-fx-background-color:blue");
}
}
};
});
}

You need to update the items of Table View by overriding updateItem() method.
The code is :
yourColumnBased.setCellFactory(column -> {
return new TableCell<CarFx, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? "" : getItem().toString());
setGraphic(null);
TableRow<CarFx> currentRow = getTableRow();
if (!isEmpty()) {
if(item.equals("assigned"))
currentRow.setStyle("-fx-background-color:blue");
else
currentRow.setStyle("-fx-background-color:green");
}
}
};
});

Related

Change specific row color in javaFX

Here is the code i write to change row color where leather's meter < 200 but i face null pointer exception in if condition. First i get all data from database and add them all to table view so i don't expect null pointer exception. What is the problem?
#FXML
TableView<Leather> tableView;
ObservableList<Leather> data = FXCollections.observableArrayList();
#Override
public void initialize(URL location, ResourceBundle resources) {
tableView.setEditable(true);
codeCol.setCellValueFactory(new PropertyValueFactory<>("code"));
colorCol.setCellValueFactory(new PropertyValueFactory<>("color"));
meterCol.setCellValueFactory(new PropertyValueFactory<>("meter"));
indexCol.setCellFactory(col -> new TableCell<Task, String>() {
#Override
public void updateIndex(int index) {
super.updateIndex(index);
if (isEmpty() || index < 0) {
setText(null);
} else {
setText(Integer.toString(index+1));
}
}
});
data.addAll(storeService.getAll());
tableView.setItems(data);
tableView.setRowFactory(tv -> new TableRow<Leather>(){
#Override
protected void updateItem(Leather item, boolean empty) {
super.updateItem(item,empty);
if (item.getMeter()<200){
setStyle("-fx-background-color: #DB8A6B");
}
}
});
}
You need to handle all cases in your rowFactory (in the same way you do in your cellFactory):
tableView.setRowFactory(tv -> new TableRow<Leather>(){
#Override
protected void updateItem(Leather item, boolean empty) {
super.updateItem(item,empty);
if (empty || item == null) {
setStyle("");
} else if (item.getMeter()<200){
setStyle("-fx-background-color: #DB8A6B");
} else {
setStyle("");
}
}
});

JafaFX ListView change Color of single Cells/Items/Rows

Probably the answer to this question is very simple, so I'm going to try to keep my post so.
My Problem
I want the Text-Color of different Cells/Rows/Items to be customizable through a JavaFX ColorPicker. My Code does work, but not really like I want it to.. Everytime a new Item is added to the ListView, the whole ListView changes its Text-Color the Text-Color chosen for the latest Item.
Here's my code (Full class linked below, but I don't think it's needed)
#FXML
void handleAdd(){ //When add button is clicked
fontSize = 16.0;
listView.setCellFactory(cell -> {
ListCell<String> cel = new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setTextFill(colorPicker.getValue());
setFont(Font.font(16));
setText(item);
} else {
setText("");
}
}
};
return cel;
});
listView.getItems().add(input.getText()); //input is my TextField
input.clear();
}
full class
Thanks in advance!
Use a item type for the ListView that contains a ObjectProperty<Color> in addition to a string
private static class ListItem {
public ListItem(String text) {
this.text = text;
}
private final String text;
private final ObjectProperty<Color> color = new SimpleObjectProperty(Color.BLACK);
}
ListView<ListItem> listView;
listView.setCellFactory(cell -> {
ListCell<ListItem> cel = new ListCell<ListItem>() {
#Override
protected void updateItem(ListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
textFillProperty().bind(item.color);
setFont(Font.font(16));
setText(item.text);
} else {
setText("");
textFillProperty().unbind();
setTextFill(Color.BLACK);
}
}
};
return cel;
});
This way you simply need to set the property to a different value, if you want to change the color, e.g:
ListItem selectedItem = listView.getSelectionModel().getSelectedItem();
if (item != null) {
item.color.set(Color.RED);
}

Making Table Column editable for float data types

I am sucessfull in making table column editable for those which refers to a string data type column of database table. But I am unsucessfull in doing the same with a float data type column of database table.
tblColProductID.setCellValueFactory(new PropertyValueFactory<ProductHeader, String>("Product_ID"));
tblColProductName.setCellFactory(TextFieldTableCell.forTableColumn());
tblColProductName.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<ProductHeader,String>>() {
#Override
public void handle(CellEditEvent<ProductHeader, String> t) {
// TODO Auto-generated method stub
((ProductHeader) t.getTableView().getItems()
.get(t.getTablePosition().getRow())).setProduct_ID((String) t.getNewValue());
}
The above tblColProductID refers to ProductID column which is has string datatype. But the code below gives me error in setCellFactory
tblColQuantity.setCellValueFactory(new PropertyValueFactory<PurchaseDetail, Float>("Quantity"));
tblColQuantity.setCellFactory(TextFieldTableCell.forTableColumn());
tblColQuantity.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<PurchaseDetail,Float>>() {
#Override
public void handle(CellEditEvent<PurchaseDetail, Float> t) {
((PurchaseDetail) t.getTableView().getItems().get(t.getTablePosition().getRow())).setQuantity((t.getNewValue()));
}
});
How do I make this second code work?
Thank you
Okay I have solved the problem and this is how I did it.
I refered to https://stackoverflow.com/a/27915420/5675550 which showed how to edit a table column with int datatype. I modified the code and made it work for float datatypes.
Here is the code :-
tblColQuantity.setCellFactory(col -> new IntegerEditingCell());
public class IntegerEditingCell extends TableCell<ProductHeader, Number> {
private final TextField textField = new TextField();
private final Pattern intPattern = Pattern.compile("\\d*\\.\\d+");
public IntegerEditingCell(){
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
processEdit();
}
});
textField.setOnAction(event -> processEdit());
}
private void processEdit() {
String text = textField.getText();
if (intPattern.matcher(text).matches()) {
commitEdit(Float.parseFloat(text));
} else {
cancelEdit();
}
}
#Override
public void updateItem(Number value, boolean empty) {
super.updateItem(value, empty);
if (empty) {
setText(null);
setGraphic(null);
}else if (isEditing()) {
setText(null);
textField.setText(value.toString());
setGraphic(textField);
} else {
setText(value.toString());
setGraphic(null);
}
}
#Override
public void startEdit() {
super.startEdit();
Number value = getItem();
if (value != null) {
textField.setText(value.toString());
setGraphic(textField);
setText(null);
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText(getItem().toString());
setGraphic(null);
}
// This seems necessary to persist the edit on loss of focus; not sure why:
#Override
public void commitEdit(Number value) {
super.commitEdit(value);
((Item)this.getTableRow().getItem()).setValue(value.floatValue());
}
}

Making normal generic class

I have many controller classes. And in each such class I'm using folliwng code many times:
tc_mt_buy_amount.setCellFactory(param -> {
return new TableCell<FaClConversionDeals, BigDecimal>(){
#Override
protected void updateItem(BigDecimal item, boolean empty) {
super.updateItem(item, empty);
if(empty || item == null){
setText("");
} else {
setText(df.format(item));
}
}
};
});
tc_mt_sell_amount.setCellFactory(param -> {
return new TableCell<FaClConversionDeals, BigDecimal>(){
#Override
protected void updateItem(BigDecimal item, boolean empty) {
super.updateItem(item, empty);
if(empty || item == null){
setText("");
} else {
setText(df.format(item));
}
}
};
});
In order to not dublicate code so many times in each class, I've created an inner classes in each controller class:
tc_mt_buy_amount.setCellFactory(param -> {
return new FormatMainColumn();
});
tc_mt_sell_amount.setCellFactory(param -> {
return new FormatMainColumn();
});
private class FormatMainColumn extends TableCell<FaClConversionDeals, BigDecimal> {
DecimalFormat df = new DecimalFormat("#,###.00");
#Override
protected void updateItem(BigDecimal item, boolean empty) {
super.updateItem(item, empty);
if(empty || item == null){
setText("");
} else {
setText(df.format(item));
}
}
}
Now, in order to not to write inner classes in each controller, I want to create standalone generic class to where I can refer from each controller. The problem is that, for instance, FaClConversionDeals in above example is different in each controller (i.e., it may be other classes). In structural way, it should look similar to this:
From controller:
tc_mt_buy_amount.setCellFactory(param -> {
return new FormatMainColumn(ClassName);
});
Generic Class:
private class FormatMainColumn(ClassName class) extends TableCell<ClassName, BigDecimal> {
DecimalFormat
df = new DecimalFormat("#,###.00");
#Override
protected void updateItem(BigDecimal item, boolean empty) {
super.updateItem(item, empty);
if(empty || item == null){
setText("");
} else {
setText(df.format(item));
}
}
}
That's not how the generics syntax works. If I understood you correctly, you want your class declared as
private class FormatMainColumn<T> extends TableCell<T, BigDecimal> {
and then you can do return new FormatMainColumn<ClassName>();.

Dynamically change the background of a cell in a ListView

I have a problem with my listview.
I have some code that changes the background of some cells in a ListView. But when i scroll in that listview the background changes to the wrong cells.
Here you see some code:
Change the background of the cell in a listview:
#Override
public ListCell<String> call(ListView<String> param) {
ListCell<String> cell = new ListCell<String>() {
#Override
protected void updateItem(String t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
setText(t);
if (!controller.checkGerecht(t)) {
if (!getStyleClass().contains("mystyleclass")) {
getStyleClass().add("mystyleclass");
foutieveInput.add(t);
} else {
getStyleClass().remove("mystyleclass");
}
} else {
setText(t);
}
}
}
The css file:
.mystyleclass{
-fx-background-color: #ff0000;
}
You have the logic implemented incorrectly, assuming you want the red background only on cells for which controller.checkGerecht(t) is false. You're trying to remove the style class if it's not present: you want to remove the style class if your condition doesn't hold. (I.e. you have remove in the wrong else clause.)
Additionally, you need to handle the case where the cell is updated to hold a null value (e.g. if it is empty):
public ListCell<String> call(ListView<String> param) {
ListCell<String> cell = new ListCell<String>() {
#Override
protected void updateItem(String t, boolean bln) {
super.updateItem(t, bln);
if (t == null) {
setText(null);
getStyleClass().remove("mystyleclass");
} else {
setText(t);
if (!controller.checkGerecht(t)) {
if (!getStyleClass().contains("mystyleclass")) {
getStyleClass().add("mystyleclass");
foutieveInput.add(t);
}
} else {
getStyleClass().remove("mystyleclass");
}
}
}
};
return cell ;
}

Categories

Resources