Change specific row color in javaFX - java

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("");
}
}
});

Related

ListView in Javafx: cell Factory

i m trying to create a ListView, that some cell base on what they have inside can not be clicked. that works fine for now but the problem is when i click an element that is disabled, it return me the that last element which i clicked.
here is how i create the ListView
public ListView<String> createStringList(int sizeX, int sizeY) {
ListView<String> list = new ListView<String>();
list.setMaxSize(sizeX, sizeY);
list.setMinSize(sizeX, sizeY);
list.setStyle("-fx-font-size:8.0;");
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else if (Main.controller.getGame().chessBot != null) {
setText(item);
String botColor = Main.controller.getGame().chessBot.getBotColor().toString();
if (botColor.equals("BLACK")) {
if (item.contains("Black") || item.contains("Schwarz")) {
setDisable(true);
}else {
setDisable(false);
}
} else {
if (item.contains("White") || item.contains("Weiß")) {
setDisable(true);
}else {
setDisable(false);
}
}
} else {
setText(item);
setDisable(false);
}
}
};
}
});
return list;
}
Here i add the list on the Pane
...
...
historyList = GUIToolCreator.getInstance().createStringList(120, 220);
//TODO:
historyList.setOnMouseClicked(e -> {
int selectedIndex = getSelecetedInHistoryList();
if (selectedIndex >= 0) {
System.out.println(Main.controller.getGame().getHistory().get(selectedIndex).getStart().toSmallString() + "-"
+ Main.controller.getGame().getHistory().get(selectedIndex).getEnd().toSmallString() + ": Color ->"
+ Main.controller.getGame().getHistory().get(selectedIndex).getColor());
} else {
System.out.println("can not be selected!");
}
});
...
...
here all i need is that this method return -1 if the selected cell is disable but instead i recieve the last cell that i clicked
public int getSelecetedInHistoryList() {
int selectedIndex = historyList.getSelectionModel().getSelectedIndex();
if (selectedIndex == -1) {
return selectedIndex;
}
System.out.println(selectedIndex);
if (Main.controller.getGame().chessBot != null) {
if (Main.controller.getGame().chessBot.getBotColor() == Main.controller.getGame().getHistory()
.get(selectedIndex).getColor()) {
selectedIndex = -1;
}
}
return selectedIndex;
}

Disable JavaFX TableColumn

Have a TableColumn defined as TableColumn<Target, String> tableColumnLocation; and is populated like this:
tableColumnLocation.setCellValueFactory(new
PropertyValueFactory<Target, String>("name"));
tableColumnLocation.setCellFactory(ComboBoxTableCell.forTableColumn(locationValues));
where locationValues are set of Strings read from a database.
Am trying to disable the tableColumnLocation dropdown in case another checkbox column is unselected. So the issue is how to disable ComboBoxTableCell. Any recommendations would be highly appreciated.
Have been able to disable other TableColumn as shown below but not sure on how to proceed on this one.
tableColumnQty.setCellFactory(
new Callback<TableColumn<Test, String>, TableCell<Test, String>>() {
#Override
public TableCell<Test, String> call(TableColumn<Test, String> paramTableColumn) {
return new TextFieldTableCell<Test, String>(new DefaultStringConverter()) {
#Override
public void updateItem(String s, boolean b) {
super.updateItem(s, b);
if(!isEmpty()) {
Test item = getTableView().getItems().get(getIndex());
if (item.getTarget().equalsIgnoreCase("0")) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-background-color: lightgrey");
} else {
setDisable(false);
setEditable(true);
//if(s != null && !s.equalsIgnoreCase(""))
setStyle("");
}
}
}
};
}
});
Here is what you need:
tableColumnLocation.setCellFactory(
new Callback<TableColumn<Target, String>, TableCell<Target, String>>() {
#Override
public TableCell<Target, String> call(TableColumn<Target, String> paramTableColumn) {
return new ComboBoxTableCell<Target, String>(new DefaultStringConverter(), locationValues) {
#Override
public void updateItem(String s, boolean b) {
super.updateItem(s, b);
if(!isEmpty()) {
Target item = getTableView().getItems().get(getIndex());
if (check if checkbox is unselected) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-background-color: lightgrey");
} else {
setDisable(false);
setEditable(true);
setStyle("");
}
}
}
};
}
});

How to get a ComboBox to use an Object's toString method instead of setting it as a graphic? [duplicate]

I have a combobox which shows list of User objects. I have coded a custom cell factory for the combobox:
#FXML ComboBox<User> cmbUserIds;
cmbUserIds.setCellFactory(new Callback<ListView<User>,ListCell<User>>(){
#Override
public ListCell<User> call(ListView<User> l){
return new ListCell<User>(){
#Override
protected void updateItem(Useritem, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId()+" "+item.getName());
}
}
} ;
}
});
ListView is showing a string(id+name), but when I select an item from listview, Combobox is showing toString() method return value i.e address of object.
I can't override toString() method, because the User domain object should be same as the one at server.
How to display id in combobox? Please suggest
EDIT1
I tried below code. Now combo box shows id when I select a value from the listview.
cmbUserIds.setConverter(new StringConverter<User>() {
#Override
public String toString(User user) {
if (user== null){
return null;
} else {
return user.getId();
}
}
#Override
public User fromString(String id) {
return null;
}
});
The selected value in combo box is cleared when control focus is lost. How to fix this?
EDIT2:
#FXML AnchorPane root;
#FXML ComboBox<UserDTO> cmbUsers;
List<UserDTO> users;
public class GateInController implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
users = UserService.getListOfUsers();
cmbUsers.setItems(FXCollections.observableList(users));
cmbUsers.getSelectionModel().selectFirst();
// list of values showed in combo box drop down
cmbUsers.setCellFactory(new Callback<ListView<UserDTO>,ListCell<UserDTO>>(){
#Override
public ListCell<UserDTO> call(ListView<UserDTO> l){
return new ListCell<UserDTO>(){
#Override
protected void updateItem(UserDTO item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getUserId()+" "+item.getUserNm());
}
}
} ;
}
});
//selected value showed in combo box
cmbUsers.setConverter(new StringConverter<UserDTO>() {
#Override
public String toString(UserDTO user) {
if (user == null){
return null;
} else {
return user.getUserId();
}
}
#Override
public UserDTO fromString(String userId) {
return null;
}
});
}
}
Just create and set a CallBack like follows:
#FXML ComboBox<User> cmbUserIds;
Callback<ListView<User>, ListCell<User>> cellFactory = new Callback<ListView<User>, ListCell<User>>() {
#Override
public ListCell<User> call(ListView<User> l) {
return new ListCell<User>() {
#Override
protected void updateItem(User item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId() + " " + item.getName());
}
}
} ;
}
}
// Just set the button cell here:
cmbUserIds.setButtonCell(cellFactory.call(null));
cmbUserIds.setCellFactory(cellFactory);
You need to provide a functional fromString() Method within the Converter!
I had the same problem as you have and as I implemented the fromString() with working code, the ComboBox behaves as expected.
This class provides a few of my objects, for dev-test purposes:
public class DevCatProvider {
public static final CategoryObject c1;
public static final CategoryObject c2;
public static final CategoryObject c3;
static {
// Init objects
}
public static CategoryObject getCatForName(final String name) {
switch (name) {
case "Kategorie 1":
return c1;
case "Cat 2":
return c2;
case "Steuer":
return c3;
default:
return c1;
}
}
}
The converter object:
public class CategoryChooserConverter<T> extends StringConverter<CategoryObject> {
#Override
public CategoryObject fromString(final String catName) {
//This is the important code!
return Dev_CatProvider.getCatForName(catName);
}
#Override
public String toString(final CategoryObject categoryObject) {
if (categoryObject == null) {
return null;
}
return categoryObject.getName();
}
}

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());
}
}

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