如何在 table 列上显示一个列表,列表项的字段很少
How to show a list on table column, with few fields of list items
更新:这个问题移到TableColumn should only show one specific value of a complex data type因为它更具体
我想用包含 name
、id
和 List<Person>
的复杂数据类型 Person
填充 table。目前我得到一个 table 和正确的 name
,id
和第三列包含其他 Person
的全部信息,但它应该只显示名称Persons
秒。
有什么方法可以让我的第三列只显示 Person.getName()
值吗?
关键字,解决方案欢迎!非常感谢!
编辑:代码
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);
}
因此,如果我填写 table id
和 name
列包含正确的名称,并且第三列(带有 List<Person>
)显示 [Person [id1, John, ...]...]]
.
现在我想问一下,是否有可能第三列只显示 id
或 name
而没有操作数据?
您可以使用长扩展版本定义单元格值工厂,您可以在其中控制要显示的字段:
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 );
});
作为 Uluk 解决方案的替代方案,请考虑在列上设置单元格工厂,而不是单元格值工厂。这些之间的选择取决于您如何看待列和模型之间的关系 (Person
)。如果您将名称列表视为列显示的数据,那么 Uluk 的解决方案就是可行的方法。如果您将 Person
个对象的列表视为数据,按名称显示,那么这将是更直观的选项:
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(", ")));
}
}
});
这样可以轻松更改列表在该列中的显示方式,例如:
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);
}
}
};
});
更新:这个问题移到TableColumn should only show one specific value of a complex data type因为它更具体
我想用包含 name
、id
和 List<Person>
的复杂数据类型 Person
填充 table。目前我得到一个 table 和正确的 name
,id
和第三列包含其他 Person
的全部信息,但它应该只显示名称Persons
秒。
有什么方法可以让我的第三列只显示 Person.getName()
值吗?
关键字,解决方案欢迎!非常感谢!
编辑:代码
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);
}
因此,如果我填写 table id
和 name
列包含正确的名称,并且第三列(带有 List<Person>
)显示 [Person [id1, John, ...]...]]
.
现在我想问一下,是否有可能第三列只显示 id
或 name
而没有操作数据?
您可以使用长扩展版本定义单元格值工厂,您可以在其中控制要显示的字段:
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 );
});
作为 Uluk 解决方案的替代方案,请考虑在列上设置单元格工厂,而不是单元格值工厂。这些之间的选择取决于您如何看待列和模型之间的关系 (Person
)。如果您将名称列表视为列显示的数据,那么 Uluk 的解决方案就是可行的方法。如果您将 Person
个对象的列表视为数据,按名称显示,那么这将是更直观的选项:
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(", ")));
}
}
});
这样可以轻松更改列表在该列中的显示方式,例如:
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);
}
}
};
});