当前位置: 首页 > 知识库问答 >
问题:

JavaFX:使用ObservableMap填充TableView,该Map的值有一个自定义类

子车文康
2023-03-14

我想在表视图中显示以下可观察地图:

private ObservableMap<String, Shape> myShapes = FXCollections.observableHashMap();

其中Shape定义如下:

public class Shape {

private StringProperty areaFormula = new SimpleStringProperty();
private IntegerProperty numSides = new SimpleIntegerProperty();

html" target="_blank">public Shape(String areaFormula, int numSides)
{
    this.areaFormula.set(areaFormula);
    this.numSides.set(numSides);
}

public String getAreaFormula() { return areaFormula.get(); }

public void setAreaFormula(String areaFormula) { this.areaFormula.set(areaFormula); }

public StringProperty areaFormulaProperty() { return this.areaFormula; }

public int getNumSides() { return numSides.get(); }

public void setNumSides(int sides) { this.numSides.set(sides); }

public IntegerProperty numSidesProperty() { return this.numSides; }
}

我希望TableView的第一列是Map键(称之为Key),第二列是myShapes。拿到钥匙。getAreaFormula(),第三列是myShapes。拿到钥匙。getnumSides()。我希望地图更改时TableView会自动更新。

如果可能的话,让用户可以编辑TableView的第二列和第三列,并在Map中更新这些编辑,这也是非常好的。

我已经问过stackoverflow,如何用ObservableMap填充TableView,以便它在这里的更改时更新:用HashMap填充TableView,HashMap更改时更新。然而,正如您在这里的讨论中所看到的,它并不像我在这里处理的那样处理自定义类。

以下是我目前的解决方案:

        ObservableMap<String, Shape> map = FXCollections.observableHashMap();

        ObservableList<String> keys = FXCollections.observableArrayList();

        map.addListener((MapChangeListener.Change<? extends String, ? extends Shape> change) -> {
            boolean removed = change.wasRemoved();
            if (removed != change.wasAdded()) {
                // no put for existing key
                if (removed) {
                    keys.remove(change.getKey());
                } else {
                    keys.add(change.getKey());
                }
            }
        });

        map.put("square", new Shape("L^2", 4));
        map.put("rectangle", new Shape("LW", 4));
        map.put("triangle", new Shape("0.5HB", 3));

        final TableView<String> table = new TableView<>(keys);

        TableColumn<String, String> column1 = new TableColumn<>("Key");

        column1.setCellValueFactory(cd -> Bindings.createStringBinding(() -> cd.getValue()));

        TableColumn<String, String> column2 = new TableColumn<>("Value");

        column2.setCellValueFactory( ... );

        table.getColumns().setAll(column1, column2);

我被卡住的地方是倒数第二行column2。setCellValueFactory(…) 。我想column2显示形状getAreaFormula()SimpleStringProperty,但我不知道如何设置CellValueFactory

谢谢你的帮助。


共有1个答案

苏凯
2023-03-14

如果您创建一个不可变键值对列表,而不是简单地创建一个键列表,那么这是最简单的。这大大降低了您需要使用的侦听器的复杂性,因为如果值被更新,并且您不需要将侦听器添加到cellValueFactory中的映射,则MapChangeListener将始终替换项:

public final class MapEntry<K, V> {

    private final K key;
    private final V value;

    public MapEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public boolean equals(Object obj) {
        // check equality only based on keys
        if (obj instanceof MapEntry) {
            MapEntry<?, ?> other = (MapEntry<?, ?>) obj;
            return Objects.equals(key, other.key);
        } else {
            return false;
        }
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }

}
ObservableMap<String, Shape> map = FXCollections.observableHashMap();

ObservableList<MapEntry<String, Shape>> entries = FXCollections.observableArrayList();

map.addListener((MapChangeListener.Change<? extends String, ? extends Shape> change) -> {
    boolean removed = change.wasRemoved();
    if (removed != change.wasAdded()) {
        if (removed) {
            // no put for existing key
            // remove pair completely
            entries.remove(new MapEntry<>(change.getKey(), (Shape) null));
        } else {
            // add new entry
            entries.add(new MapEntry<>(change.getKey(), change.getValueAdded()));
        }
    } else {
        // replace existing entry
        MapEntry<String, Shape> entry = new MapEntry<>(change.getKey(), change.getValueAdded());

        int index = entries.indexOf(entry);
        entries.set(index, entry);
    }
});

map.put("one", new Shape("a", 1));
map.put("two", new Shape("b", 2));
map.put("three", new Shape("c", 3));

final TableView<MapEntry<String, Shape>> table = new TableView<>(entries);
TableColumn<MapEntry<String, Shape>, String> column1 = new TableColumn<>("Key");

// display item value (= constant)
column1.setCellValueFactory(cd -> Bindings.createStringBinding(() -> cd.getValue().getKey()));

TableColumn<MapEntry<String, Shape>, String> column2 = new TableColumn<>("formula");
column2.setCellValueFactory(cd -> cd.getValue().getValue().areaFormulaProperty());

TableColumn<MapEntry<String, Shape>, Number> column3 = new TableColumn<>("sides");
column3.setCellValueFactory(cd -> cd.getValue().getValue().numSidesProperty());

table.getColumns().setAll(column1, column2, column3);
 类似资料:
  • 我在互联网上找不到正确的答案,如何用ObservableMap作为MapProperty填充tableviw。我想在按值排序的tableview中显示文章。

  • 我的Java程序产生了很多数据,我用它构建了单个的ResultObject。因为只有某些结果对象会引起兴趣,所以我填充了一个可观察的HashMap 虽然映射和处理这些结果按预期工作,但我很难用该ObservableHashMap填充TableView 我的CustomObject(如果两个CustomObject具有相同的属性,只需检查JSONObject): 我的ObservableHashMa

  • //控制器类Mainguicontroller.java

  • 我正在为一个游戏开发Javafx应用程序。我有一些数据存储在枚举中,但似乎不知道如何轻松地将数据添加到JavaFX TableView,有人能帮我一下吗。我将使用fxml为TableView设置样式。 我希望每一个枚举vallue都在一个单独的行中,在我希望的列中: 图标为图像。 按整数排序。 级别为整数。 经验值为整数。 枚举:

  • 我有一个用SceneBuilder生成的TableView,所有列都是从其他视图导入的FXML,直到没有问题为止,但列没有填充宽度。 我试图用scene builder和FXML来解决这个问题,但没有运气,所有的大小都是计算出来的。 我尝试用一个change listener对其进行编码,它在每次窗口改变大小以适应列的大小时都会进行检查。 这样可以工作,并且列的大小调整到适当的宽度(基本上我得到了

  • 我很难用ObservableList中获得的数据填充JavaFX中的表视图。 当在病人信息控制器中按下btn确认()时,它会使用病人信息控制器视图中的屏幕文本数据创建一个病人对象。 然后将该对象添加到队列类中的LinkedList队列中。然后返回队列并将其传递给QueueTabPageController方法displayQueue() 我知道,当我将增强的for循环打印到控制台时,患者对象获得了