我同意@kleopatra的评论。不能在单元格内进行复杂的数据处理。通常,Row/Cell/updateItem()应该更关注“如何/呈现什么”。我可以给你建议一些关键的方向,你可以看看。
如果要根据某个项中的某些更新(不是因为add/remove item,而是因为某个项的某个属性中的更新)来更新行样式,则必须首先侦听更改。
因此,您将在TableView中设置的ObservalList应该注册/声明如下:
ObservableList<Person> persons = FXCollections.observableArrayList(e ->
new Observable[]{e.pointsProperty()});
下面是一个快速工作的演示,在每次更新Points列时突出显示该行3秒钟。我希望这个演示可以给你一些输入来解决你的问题。这是一种方法。有更多更好的方法可以实现以下功能。你仍然可以使用@fabian解决方案。
注:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.Duration;
import java.security.SecureRandom;
public class TableRowUpdateHighlightDemo extends Application {
private final SecureRandom rnd = new SecureRandom();
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Person> persons = FXCollections.observableArrayList(e -> new Observable[]{e.pointsProperty()});
persons.add(new Person("Harry", "John"));
persons.add(new Person("Mary", "King"));
persons.add(new Person("Don", "Bon"));
persons.add(new Person("Pink", "Wink"));
TableView<Person> tableView = new TableView<>();
TableColumn<Person, String> fnCol = new TableColumn<>("First Name");
fnCol.setCellValueFactory(param -> param.getValue().firstNameProperty());
TableColumn<Person, String> lnCol = new TableColumn<>("Last Name");
lnCol.setCellValueFactory(param -> param.getValue().lastNameProperty());
TableColumn<Person, Integer> pointsCol = new TableColumn<>("Points");
pointsCol.setCellValueFactory(param -> param.getValue().pointsProperty().asObject());
tableView.getStylesheets().add(this.getClass().getResource("tableColor.css").toExternalForm());
tableView.getColumns().addAll(fnCol, lnCol, pointsCol);
tableView.setItems(persons);
tableView.getItems().addListener((ListChangeListener<Person>) c -> {
if (c.next()) {
if (c.wasUpdated()) {
tableView.getItems().get(c.getFrom()).setHightlight(true);
tableView.refresh();
}
}
});
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
@Override
public TableRow<Person> call(TableView<Person> param) {
return new TableRow<Person>() {
Timeline highlightTL;
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
removeHighlight();
if (item != null && item.isHightlight()) {
getStyleClass().add("highlightedRow");
getHighlightTL().playFromStart();
}
}
private void removeHighlight() {
getHighlightTL().stop();
getStyleClass().removeAll("highlightedRow");
}
private Timeline getHighlightTL() {
if (highlightTL == null) {
// After 3 secs, the hightlight will be removed.
highlightTL = new Timeline(new KeyFrame(Duration.millis(3000), e -> {
getItem().setHightlight(false);
removeHighlight();
}));
highlightTL.setCycleCount(1);
}
return highlightTL;
}
};
}
});
Scene sc = new Scene(tableView);
primaryStage.setScene(sc);
primaryStage.show();
// Updating points every 5 secs to a random person.
Timeline tl = new Timeline(new KeyFrame(Duration.millis(5000), e -> {
Person p = persons.get(rnd.nextInt(4));
p.setPoints(p.getPoints() + 1);
}));
tl.setCycleCount(Animation.INDEFINITE);
tl.play();
}
class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty lastName = new SimpleStringProperty();
private IntegerProperty points = new SimpleIntegerProperty();
private BooleanProperty hightlight = new SimpleBooleanProperty();
public Person(String fn, String ln) {
setFirstName(fn);
setLastName(ln);
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public int getPoints() {
return points.get();
}
public IntegerProperty pointsProperty() {
return points;
}
public void setPoints(int points) {
this.points.set(points);
}
public boolean isHightlight() {
return hightlight.get();
}
public BooleanProperty hightlightProperty() {
return hightlight;
}
public void setHightlight(boolean hightlight) {
this.hightlight.set(hightlight);
}
}
}
更新::
如果您可以设法在外部(3secs之后)更新“hightlight”属性值,那么在RowFactory中就不需要时间线。只需在ListChangeListener中调用tableView.refresh()就可以做到这一点:)