如何使用 Set as base for TableView

How use Set as base for TableView

我已经开发了一些代码并且我有一个 SetUsers:

public class ParkCentral{
    private Set<User> users = new HashSet<>();
}

然后,在另一个 class 中,我正在开发一个 GUI 和一个 Users 的 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());