如何使用 Set as base for TableView
How use Set as base for TableView
我已经开发了一些代码并且我有一个 Set
的 User
s:
public class ParkCentral{
private Set<User> users = new HashSet<>();
}
然后,在另一个 class 中,我正在开发一个 GUI 和一个 User
s 的 TableView。
问题是我无法从 Set
创建 ObervableList
。我希望 对 ParkCentral.users
的更改会反映在 TableView 上。
无需更改 ParkCentral
实现,无需将 Set
更改为 List
?
为什么 TableView 只能与 ObservableList 一起使用,而不能与 ObservableSet 或 ObservableMap 一起使用?
您可以尝试使用自定义列:
TableColumn<ParkCentral, Void> myCol = new TableColumn<>("NameColumn");
myCol.setPrefWidth(150);
myCol.setCellFactory(col->{
TableCell<ParkCentral, Void> cell = new TableCell<ParkCentral, Void>()
{
@Override
public void updateItem(Void item, boolean empty)
{
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
HBox h = new HBox();
ParckCentral myObj = getTableView().getItems().get(getIndex());
//call any method/variable from myObj that you need
//and put the info that you want show on the cell on labels, buttons, images, etc
h.getChildren().addAll(label, button, etc...);
setGraphic(h);
}
}
};
return cell;
});
Why TableView only works with ObservableList and not with ObservableSet or ObservableMap?
A TableView
显示了一个有序的项目集合。都没有Map
Set
也不满足这些要求(某些实现除外)。
虽然可以收听 Set
中的更改并在 List
中进行适当的更改。但是,仅使用 HashSet
是不可能的;根本没有办法观察这个集合;进行更改后,您始终需要手动更新列表。
改用 ObservableSet
允许您添加一个侦听器来更新列表。
public class SetContentBinding<T> {
private final ObservableSet<T> source;
private final Collection<? super T> target;
private final SetChangeListener<T> listener;
public SetContentBinding(ObservableSet<T> source, Collection<? super T> target) {
if (source == null || target == null) {
throw new IllegalArgumentException();
}
this.source = source;
this.target = target;
target.clear();
target.addAll(source);
this.listener = c -> {
if (c.wasAdded()) {
target.add(c.getElementAdded());
} else {
target.remove(c.getElementRemoved());
}
};
source.addListener(this.listener);
}
/**
* dispose the binding
*/
public void unbind() {
source.removeListener(listener);
}
}
用法示例:
public class ParkCentral{
private ObservableSet<User> users = FXCollections.observableSet(new HashSet<>());
}
new SetContentBinding(parkCentral.getUsers(), tableView.getItems());
我已经开发了一些代码并且我有一个 Set
的 User
s:
public class ParkCentral{
private Set<User> users = new HashSet<>();
}
然后,在另一个 class 中,我正在开发一个 GUI 和一个 User
s 的 TableView。
问题是我无法从 Set
创建 ObervableList
。我希望 对 ParkCentral.users
的更改会反映在 TableView 上。
无需更改 ParkCentral
实现,无需将 Set
更改为 List
?
为什么 TableView 只能与 ObservableList 一起使用,而不能与 ObservableSet 或 ObservableMap 一起使用?
您可以尝试使用自定义列:
TableColumn<ParkCentral, Void> myCol = new TableColumn<>("NameColumn");
myCol.setPrefWidth(150);
myCol.setCellFactory(col->{
TableCell<ParkCentral, Void> cell = new TableCell<ParkCentral, Void>()
{
@Override
public void updateItem(Void item, boolean empty)
{
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
HBox h = new HBox();
ParckCentral myObj = getTableView().getItems().get(getIndex());
//call any method/variable from myObj that you need
//and put the info that you want show on the cell on labels, buttons, images, etc
h.getChildren().addAll(label, button, etc...);
setGraphic(h);
}
}
};
return cell;
});
Why TableView only works with ObservableList and not with ObservableSet or ObservableMap?
A TableView
显示了一个有序的项目集合。都没有Map
Set
也不满足这些要求(某些实现除外)。
虽然可以收听 Set
中的更改并在 List
中进行适当的更改。但是,仅使用 HashSet
是不可能的;根本没有办法观察这个集合;进行更改后,您始终需要手动更新列表。
改用 ObservableSet
允许您添加一个侦听器来更新列表。
public class SetContentBinding<T> {
private final ObservableSet<T> source;
private final Collection<? super T> target;
private final SetChangeListener<T> listener;
public SetContentBinding(ObservableSet<T> source, Collection<? super T> target) {
if (source == null || target == null) {
throw new IllegalArgumentException();
}
this.source = source;
this.target = target;
target.clear();
target.addAll(source);
this.listener = c -> {
if (c.wasAdded()) {
target.add(c.getElementAdded());
} else {
target.remove(c.getElementRemoved());
}
};
source.addListener(this.listener);
}
/**
* dispose the binding
*/
public void unbind() {
source.removeListener(listener);
}
}
用法示例:
public class ParkCentral{
private ObservableSet<User> users = FXCollections.observableSet(new HashSet<>());
}
new SetContentBinding(parkCentral.getUsers(), tableView.getItems());