问题
UPDATE: This qustion moved to TableColumn should only show one specific value of a complex data type because it's more specific
I want to populate a table with a complex data type Person
containing name
, id
and a List<Person>
. At the moment I get a table with the correct name
, id
and a third column with the whole information of other Person
s but it should only show the name of the Persons
s.
Is there any way that my third column shows only the Person.getName()
values?
Keywords, solutions welcome! Thank you very much!
Edit: Code
Person.class
public class Person {
String id;
String name;
List<Person> friends;
public String getId() {...}
public String getName() {....}
public List<Person> getFriends {...}
}
TableView.class
public TableView<Person> createTable() {
TableColumn<Person, String> firstCol = new TableColumn<>("ID");
TableColumn<Person, String> secondCol = new TableColumn<>("Name");
TableColumn<Person, List<Person> thirdCol = new TableColumn<>("Friends");
PropertyValueFactory<Person, String> firstColFactory = new PropertyValueFactory<>(
"id");
PropertyValueFactory<Person, String> secondColFactory = new PropertyValueFactory<>(
"name");
PropertyValueFactory<Person, List<Person>> thirdColFactory = new PropertyValueFactory<>(
"friends");
firstCol.setCellValueFactory(firstColFactory);
secondCol.setCellValueFactory(secondColFactory);
thirdCol.setCellValueFactory(thirdColFactory);
myTableView.getColumns().addAll(firstCol, secondCol, thirdCol);
}
So if I fill the table id
and name
-colums contain the correct name and the third column (with List<Person>
) shows [Person [id1, John, ...]...]]
.
And now I want to ask if theres a possibility that the third column only displays the id
or name
without manipulating the data?
回答1:
As an alternative to Uluk's solution, consider setting the cell factory on the column, instead of the cell value factory. The choice between these depends on how you regard the relationship between the column and the model (Person
). If you consider the list of names to be the data displayed by the column, then Uluk's solution is the way to go. If you consider the list of Person
objects to be the data, which are displayed by their names, then this will be the more intuitive option:
TableColumn<Person, List<Person> thirdCol = new TableColumn<>("Friends");
PropertyValueFactory<Person, List<Person>> thirdColFactory = new PropertyValueFactory<>("friends");
thirdCol.setCellValueFactory(thirdColFactory);
thirdCol.setCellFactory(col -> new TableCell<Person, List<Person>>() {
@Override
public void updateItem(List<Person> friends, boolean empty) {
super.updateItem(friends, empty);
if (empty) {
setText(null);
} else {
setText(friends.stream().map(Person::getName)
.collect(Collectors.joining(", ")));
}
}
});
This makes it easy to change the way the list is displayed in that column, e.g.:
thirdCol.setCellFactory( col -> {
ListView<Person> listView = new ListView<>();
listView.setCellFactory(lv -> new ListCell<Person>() {
@Override
public void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (empty) {
setText(null);
} else {
setText(person.getName());
}
}
});
return new TableCell<Person, List<Person>>() {
@Override
public void updateItem(List<Person> friends, boolean empty) {
super.updateItem(friends, empty);
if (empty) {
setGraphic(null);
} else {
listView.getItems().setAll(friends);
setGraphic(listView);
}
}
};
});
回答2:
You may define cell value factory with the long expanded version where you control which fields to show:
thirdColFactory.setCellValueFactory(
( TableColumn.CellDataFeatures<Person, String> p ) ->
{
List<Person> friends = p.getValue().getFriends();
String val = friends
.stream()
.map( item -> item.getName() )
.reduce( "", ( acc, item ) -> acc + ", " + item );
return new ReadOnlyStringWrapper( val );
});
来源:https://stackoverflow.com/questions/31126123/how-to-show-a-list-on-table-column-with-few-fields-of-list-items