Java 将ComboBoxitemsProperty绑定到MapkeySet
对于我正在做的事情,我需要将javafx.scene.control.ComboBox的成员设置为MapkeySet集合的成员 组合框中可用的选项需要随着地图的键的更新而更新。基本上,我想使用组合框从映射中选择成员,这将在运行时更新 不幸的是,ComboBoxitemsProperty.BindObservalEvalue和ComboBoxitemsProperty.SetObservalElist都不会使用集合,因此将itemsProperty连接到MapkeySet的直接路径不起作用 基本上: 如何使组合框的项成为映射键集的成员? 同样,我需要的行为是组合框的项将反映我的映射的键集。Map可以是Map的任何实现 编辑:问题似乎是从集合(在本例中为集合)中创建ObservableList,而不是将其作为副本,而是对集合的引用,以便ObservableList反映集合的内容。如果您有ObservableMap,您可以向其添加侦听器。例如:Java 将ComboBoxitemsProperty绑定到MapkeySet,java,javafx,java-8,javafx-8,Java,Javafx,Java 8,Javafx 8,对于我正在做的事情,我需要将javafx.scene.control.ComboBox的成员设置为MapkeySet集合的成员 组合框中可用的选项需要随着地图的键的更新而更新。基本上,我想使用组合框从映射中选择成员,这将在运行时更新 不幸的是,ComboBoxitemsProperty.BindObservalEvalue和ComboBoxitemsProperty.SetObservalElist都不会使用集合,因此将itemsProperty连接到MapkeySet的直接路径不起作用 基本上
ComboBox<String> comboBox = ... ;
ObservableMap<String, Something> map = ... ;
map.addListener((MapChangeListener.Change<? extends String, ? extends Something> c) ->
comboBox.getItems().setAll(map.keySet()));
下面是一个SSCCE,演示了这两种技术:
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BindItemsToKeySet extends Application {
@Override
public void start(Stage primaryStage) {
ObservableMap<Integer, Item> itemLookupById = FXCollections.observableHashMap();
ComboBox<Integer> listenerCombo = new ComboBox<>();
ComboBox<Integer> bindingCombo = new ComboBox<>();
itemLookupById.addListener((MapChangeListener.Change<? extends Integer, ? extends Item> c) ->
listenerCombo.getItems().setAll(itemLookupById.keySet())
);
bindingCombo.itemsProperty().bind(Bindings.createObjectBinding(() ->
FXCollections.observableArrayList(itemLookupById.keySet()),
itemLookupById));
TextField textField = new TextField();
textField.setOnAction(e -> {
if (textField.getText().isEmpty()) {
return ;
}
Item item = new Item(textField.getText());
itemLookupById.put(item.getId(), item);
textField.clear();
});
textField.setTooltip(new Tooltip("Type an item name and press enter"));
VBox root = new VBox(10,
textField,
listenerCombo,
bindingCombo);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 350));
primaryStage.show();
}
public static class Item {
private final int id ;
private final String name ;
private final static AtomicInteger nextID = new AtomicInteger(1000);
public Item(String name) {
this.id = nextID.incrementAndGet();
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}
你能用可观察地图作为地图吗?是的,地图可以是可观察地图。但是,将itemsProperty绑定或设置为ObservableList;我需要一个ObservableList。您可以向ObservableMap添加一个侦听器,或者创建一个自定义绑定。请看答案。我不知道我做错了什么,但第一个添加组合框作为ObservaleMap的侦听器。不过,我还是能够让绑定工作。谢谢我直接在这里输入,没有测试,所以可能有错误。我会在有机会的时候检查的。是的,我把更改的类型参数搞错了。修复并添加了一个示例。很好的解决方案!
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BindItemsToKeySet extends Application {
@Override
public void start(Stage primaryStage) {
ObservableMap<Integer, Item> itemLookupById = FXCollections.observableHashMap();
ComboBox<Integer> listenerCombo = new ComboBox<>();
ComboBox<Integer> bindingCombo = new ComboBox<>();
itemLookupById.addListener((MapChangeListener.Change<? extends Integer, ? extends Item> c) ->
listenerCombo.getItems().setAll(itemLookupById.keySet())
);
bindingCombo.itemsProperty().bind(Bindings.createObjectBinding(() ->
FXCollections.observableArrayList(itemLookupById.keySet()),
itemLookupById));
TextField textField = new TextField();
textField.setOnAction(e -> {
if (textField.getText().isEmpty()) {
return ;
}
Item item = new Item(textField.getText());
itemLookupById.put(item.getId(), item);
textField.clear();
});
textField.setTooltip(new Tooltip("Type an item name and press enter"));
VBox root = new VBox(10,
textField,
listenerCombo,
bindingCombo);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 350));
primaryStage.show();
}
public static class Item {
private final int id ;
private final String name ;
private final static AtomicInteger nextID = new AtomicInteger(1000);
public Item(String name) {
this.id = nextID.incrementAndGet();
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}