问题
I have a Java FX8 Table, I have populated it using an observable list. The table is displaying the populated data.
During user interaction a new row is created, I add this new data to the observable list. The table gets refreshed.
I know how to move focus as well as to scroll to this newly added row. However I want this row to be highlighted to show that it is newly added.
How do I get a reference to the whole row as a Node, so that I can use this node value to highlight the row.
回答1:
Use a rowFactory on the TableView which creates a TableRow. That TableRow is the Node representing the whole row. The slightly tricky part is identifying when the row represents a "recently added row".
I would approach this as follows. I'll use the usual contact table example
- Define an
ObjectProperty<Person>to represent the recently added person. Most of the time this will benullbut when a newPersonis added to the list, it will be set to that newPerson:
final ObjectProperty<Person> recentlyAddedPerson = new SimpleObjectProperty<>();
Register a
ListListenerwith the table's items list. When a new item is added to the list, update therecentlyAddedPerson. Since you don't want the new person to be labeled as "new" indefinitely, start a pause transition that will resetrecentlyAddedPersontonullafter some delay (a second or two).:final Duration timeToGetOld = Duration.seconds(1.0); table.getItems().addListener((Change<? extends Person> change) -> { while (change.next()) { if (change.wasAdded()) { List<? extends Person> addedPeople = change.getAddedSubList(); Person lastAddedPerson = addedPeople.get(addedPeople.size()-1); recentlyAddedPerson.set(lastAddedPerson); // set back to null after a short delay, unless changed since then: PauseTransition agingTime = new PauseTransition(timeToGetOld); agingTime.setOnFinished(event -> { if (recentlyAddedPerson.get() == lastAddedPerson) { recentlyAddedPerson.set(null); } }); agingTime.play(); } } });Create a row factory for the table. This row factory returns a custom
TableRow. This customTableRowcreates aBooleanBindingwhich is set to true if this row represents a recently-added row. (This will be true if the row's item is not null and is equal to therecentlyAddedPersondefined above.)To actually implement the highlighting, I would just use a CSS PseudoClass. The implementation of the highlighting then becomes trivial; just set the pseudoclass state to the value in the
BooleanBindingdefined in theTableRowimplementation.
So you'll need something like:
final PseudoClass newPersonPseudoClass = PseudoClass.getPseudoClass("new");
and the rowFactory looks like
table.setRowFactory(tableView -> new TableRow<Person>() {
// Bindings API uses weak listeners, so this needs to be a field to
// make sure it stays in scope as long as the TableRow is in scope.
private final BooleanBinding itemIsNewPerson
= Bindings.isNotNull(itemProperty())
.and(Bindings.equal(itemProperty(), recentlyAddedPerson));
{
// anonymous constructor:
itemIsNewPerson.addListener((obs, wasNew, isNew)
-> pseudoClassStateChanged(newPersonPseudoClass, isNew));
}
});
Finally, just add the following css to your stylesheet:
.table-row-cell:new {
-fx-background-color: darkseagreen ;
}
I posted the complete example as a gist.
来源:https://stackoverflow.com/questions/24166995/java-fx-8-table-row-highlighting