javaFX tableview can not correct render row - javafx

if I add more items into table until it generate a scroll bar. At this time, when I scrolled scroll bar, first name not equal "Jacob" was rendered yellow.
enter image description here
table.setRowFactory(row -> new TableRow<Person>() {
#Override
public void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
} else {
if (item.getFirstName().equals("Jacob")) {
setStyle("-fx-background-color: yellow");
}
}
}
});

When you scroll, the rows are reused to represent new items that are displayed. Your row factory never removes a style once it is set, so any rows that were yellow remain yellow no matter which items they are reused for.
In other words, once a particular row displays a person with first name "Jacob", that row will turn yellow, and then the style will never change (it will always stay yellow), even if the row is reused to display another person.
You need to reset the style if it the row should not be yellow:
table.setRowFactory(row -> new TableRow<Person>() {
#Override
public void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setStyle("");
} else {
if (item.getFirstName().equals("Jacob")) {
setStyle("-fx-background-color: yellow");
} else {
setStyle("");
}
}
}
});

Related

JavaFX ListView mirroring content at the end

When I add new item to my ListView, it starts mirroring all the content at the end it's layout (it's not clickable) does somebody know what can cause it? Thanks.
Ok, I found the problem.
I have the list of objects and want it to display the title of object as list node text.
The problem is that I wrongly defined the custom cell factory.
tagListView.setCellFactory(param -> new ListCell<>() {
#Override
protected void updateItem(StoreTagVoImpl item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setText(item.getTitle());
}
}
});
But it should be as this:
tagListView.setCellFactory(param -> new ListCell<>() {
#Override
protected void updateItem(StoreTagVoImpl item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getTitle());
}
}
});

JavaFX TableView scrolling colors different row that aren't ment to be colored

Forum,
I have created a Tableview. Every row is filled with the information given by each "Steckerpin"-object. Using RowFactory I color the backround of each row depending on the value of the attribute "Zustand" of every object ("Steckerpin").
The problem is, when the table becomes scrollable, the new appearing row are coloured in a similar order as the colored rows in the beginning. But those rows shouldn't be colored, because their attribute "Zustand" hasn't changed.
Colored rows before scrolling
New appearing rows after scrolling
If I scroll to the end of the table, the wrong colored rows become white again.
I have read that it is a common problem using tableviews in combination with RowFactory, because the rows are reused once you start scrolling.
Here is my code using the RowFactory:
durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {
#Override
public void updateItem(Steckerpin item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
setStyle("");
} else if (item.getZustand().equals(okZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), true);
} else if (item.getZustand().equals(fehlerZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), true);
} else if (item.getZustand().equals(prüfZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), true);
}
}
});
I have read a couple of similar questions, but I can't find a solution for my problem. So I would be very grateful for some help.
When you scroll, existing rows are reused to display new items. So, for example, if you had a row which displayed an item which was in an "error" state, and it is reused for an item which is in an "ok" state, then both pseudoclasses will be set to true.
Consequently, you need to set all pseudoclasses to the correct state under all conditions:
durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {
#Override
public void updateItem(Steckerpin item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
setStyle("");
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
} else if (item.getZustand().equals(okZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), true);
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
} else if (item.getZustand().equals(fehlerZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), true);
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
} else if (item.getZustand().equals(prüfZustString)) {
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), true);
} else {
pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
}
}
});
Equivalently, with less code:
durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {
private final List<String> states = List.of("ok", "error", "pending");
#Override
public void updateItem(Steckerpin item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
setStyle("");
updateState(null);
} else if (item.getZustand().equals(okZustString)) {
updateState("ok");
} else if (item.getZustand().equals(fehlerZustString)) {
updateState("error");
} else if (item.getZustand().equals(prüfZustString)) {
updateState("pending");
} else {
updateState(null);
}
}
private void updateState(String newState) {
states.forEach(state ->
pseudoClassStateChanged(PseudoClass.getPseudoClass(state), state.equals(newState)));
}
});

Javafx treeview adding extra icons randomly to the view

I am using javafx treeview and i added icons to my tree view.
I use the following code to add the icon to a treeitem. Using Jfeniox library for material design icon. When i click on the tree item the icons appears randomly to the end of the treeview list like in image.
rootTreeView.setCellFactory(tv -> new TreeCell<LeafItem>() {
#Override
public void updateItem(final LeafItem item, final boolean empty) {
super.updateItem(item, empty);
setText(null);
setTooltip(null);
setContextMenu(null);
if (!empty) {
if (getTreeItem().equals(rootTreeItem)) {
if (item == null) {
setText("sasa");
}
}
if (item instanceof Project) {
final Project project = (Project) item;
setText(project.getName());
setGraphic(createIcon(MaterialDesignIcon.FOLDER));
}
}
}
});
private MaterialDesignIconView createIcon(final MaterialDesignIcon icon) {
final MaterialDesignIconView materialDesignIconView = new MaterialDesignIconView(
icon);
materialDesignIconView.setSize("1.5em");
materialDesignIconView.setStyleClass("icon-color");
return materialDesignIconView;
}
In the updateItem method of the cell you do not set the graphic property to null in case the cell is empty or the item is not a instance of Project. Since items can be reassigned to the cell you need to do this in order to remove the icon from the cell:
#Override
public void updateItem(final LeafItem item, final boolean empty) {
super.updateItem(item, empty);
setText(null);
setTooltip(null);
setContextMenu(null);
setGraphic(null);
...

JavaFX - bug in cell render after hiding columns

First of all sorry for my English:)
I have a strange bug... I'd like to hide some columns in JavaFX TableView after pressing the button. The code is as simple as possible:
column8.visibleProperty().set(false);
column9.visibleProperty().set(false);
(I also tested with remove with the same result).
The problem is that in "neighboring cell" I have "separator" from somewhere after this action.
I use Cellfactories is my code. For one of the hidden Cell it is
column8.setCellFactory(column -> {
return new TableCell<Anfrage, Mandant>() {
#Override
protected void updateItem(Mandant item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getNameMandant());
}
}
};
});
And for cell, where I have "separator" after hiding:
//Store
column10.setCellFactory(column -> {
return new TableCell<Anfrage, Terminals>() {
#Override
protected void updateItem(Terminals item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getStore());
}
}
};
});
Some pics to explain what is actually wrong.
If i set visible to "true" again everythings works as expected - all columns are in there without any "separators" anywhere.
Thanks a lot for any advice!
So, finally tableview refreshing is resolved in JavaFX 8u60. Now "native" table.refresh() do the trick.

Colouring table row in JavaFX

This question is related to this. Now I want to colour the row where field value equals to some value.
#FXML
private TableView<FaDeal> tv_mm_view;
#FXML
private TableColumn<FaDeal, String> tc_inst;
tc_inst.setCellValueFactory(cellData -> new SimpleStringProperty(""+cellData.getValue().getInstrumentId()));
tc_inst.setCellFactory(column -> new TableCell<FaDeal, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item);
// Style row where balance < 0 with a different color.
TableRow currentRow = getTableRow();
if (item.equals("1070")) {
currentRow.setStyle("-fx-background-color: tomato;");
} else currentRow.setStyle("");
}
}
});
The problem is I don't want to show tc_inst in my table. For this reason I set visible checkbox in SceneBuilder to false. In this case colouring part doesn't work at all. How can hide tc_inst so that colouring works?
Use a row factory, instead of a cell factory, if you want to change the color of the whole row:
tv_mm_view.setRowFactory(tv -> new TableRow<FaDeal>() {
#Override
public void updateItem(FaDeal item, boolean empty) {
super.updateItem(item, empty) ;
if (item == null) {
setStyle("");
} else if (item.getInstrumentId().equals("1070")) {
setStyle("-fx-background-color: tomato;");
} else {
setStyle("");
}
}
});
Note that if the value of instrumentId changes while the row is displayed, then the color will not change automatically with the above code, unless you do some additional work. The simplest way to make that happen would be to construct your items list with an extractor which returned the instrumentIdProperty() (assuming you are using the JavaFX property pattern in FaDeal).

Resources