Reputation: 1446
I am getting the row from tableView. I use setRowFactory to get row and later I am using it.
I need to override updateItem method to get each row and if item inside that row has error, then use red colour otherwise use green.
The item inside of the row is "history" object, because rows are pieces of history - history, which was created after doing some action in the application.
So I have something like this:
@Override
protected void updateItem(History history, boolean empty) {
super.updateItem(history, empty);
if (empty) {
setStyle("");
} else if (history.isHasError() == true) {
getStyleClass().clear();
getStyleClass().add("errorHistoryRow");
} else if (history.isHasError() == false){
getStyleClass().clear();
getStyleClass().add("");
}
}
But I need to add this updateItem to already defined row in this method.
private void openErrorMessageAfterHoveringOverRow() {
historyTableView.setRowFactory(tableView -> {
final TableRow<History> row = new TableRow<>();
for (History history : model.getAllHistoryObservableArrayList()) {
***I NEED TO PUT IT HERE***
}
for (History his : model.getAllHistoryObservableArrayList()) {
row.hoverProperty().addListener((observable) -> {
History historyRow = row.getItem();
Point p = MouseInfo.getPointerInfo().getLocation();
int x = p.x;
int y = p.y;
Popup popup = new Popup();
popup.setX(x - 300);
popup.setY(y - 200);
TextArea ta = new TextArea();
AnchorPane layout = new AnchorPane();
Scene scene = new Scene(layout);
stageSingleton().setScene(scene);
if (row.isHover() && his.equals(historyRow)) {
ta.setText(row.getItem().getErrorMessage());
popup.getContent().addAll(ta);
stageSingleton().show();
popup.show(stageSingleton());
} else if (!row.isHover() && his.equals(historyRow)) {
popup.hide();
stageSingleton().close();
}
});
}
return row;
});
}
So how can I, please, implement method updateItem to already defined row in this method? Because methods below works but I cannot have 2 different "setRowFactory" methods in my project. So I need to merge them in one method.
public void test() {
historyTableView.setRowFactory(tableView -> new TableRow<History>() {
@Override
protected void updateItem(History history, boolean empty) {
super.updateItem(history, empty);
if (empty) {
setStyle("");
} else if (history.isHasError() == true) {
getStyleClass().clear();
getStyleClass().add("errorHistoryRow");
} else if (history.isHasError() == false){
getStyleClass().clear();
getStyleClass().add("");
}
}
});
}
Upvotes: 0
Views: 402
Reputation: 82491
It's impossible to use different rowFactory
s (at least you cannot remove the rows that were already created). You need to combine the functionality in the rows returned by your rowFactory
.
Some additional notes:
table-row-cell
style class). It's easier to use a pseudoclass in this case. Moreover adding the empty string as style class is not beneficial in any way.InvalidationListener
for the hover
property. This kind of listener is triggered every time the value changes, if it changes from true
to false
or the other way round. public class HistoryRow extends TableRow<History> {
private static final PseudoClass ERROR = PseudoClass.getPseudoClass("error");
public HistoryRow() {
hoverProperty().addListener((o, oldValue, newValue) -> {
if (newValue) {
History historyRow = getItem();
if (historyRow != null && historyRow.isHasError()) {
// TODO: display popup here
}
}
});
}
@Override
protected void updateItem(History history, boolean empty) {
super.updateItem(history, empty);
pseudoClassStateChanged(ERROR, !empty && history != null && history.isHasError());
}
}
In your CSS stylesheet changing from style class to pseudoclass requires you to adjust the selectors. You need to use the :error
pseudoclass selector instead of the .errorHistoryRow
class selector.
Dynamically changing from erroneous history element to non-erroneous and the other way round could be done by adding a BooleanProperty
to History
and adding/removing a listener in the updateItem
method, if necessary.
Upvotes: 1