JavaFX:使用ObservableMap填充TableView,该ObservableMap的值为

时间:2016-07-20 18:07:44

标签: java javafx tableview

我想要在TableView中显示以下ObservableMap:

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

Shape的定义如下:

public class Shape {

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

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(称之为key),第二列是myShapes.get(key).getAreaFormula(),第三列是myShapes.get(key).getnumSides()。我希望TableView在Map更改时自动更新。

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

我已经询问了有关使用ObservableMap填充TableView的stackoverflow,以便在此处更新更改: Populating a TableView with a HashMap that will update when HashMap changes。但是正如你在那里的讨论中所看到的那样,它没有像我这里那样处理自定义类。

到目前为止,这是我的解决方案:

        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显示Shape getAreaFormula() SimpleStringProperty,但我不知道如何设置CellValueFactorydelete_these_indexes.each_with_index do |val, i| my_array.delete_at(val - i) end 这样做。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

这是最简单的,如果您创建一个不可变键值对列表而不是简单的键列表。这大大降低了您需要使用的侦听器的复杂性,因为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); <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"> $(document).ready(function(){ var myCookie = getCookie("helpText"); if (typeof myCookie === 'undefined') { // close the div in 8 secs window.setTimeout( closeHelpDiv, 8000 ); } function closeHelpDiv(){ document.getElementById("helpdiv").style.display=" none"; } function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); if (parts.length == 2) return parts.pop().split(";").shift(); } }); </script> s:

键值对类

<script type="text/javascript"> 
    jQuery(document).ready(function($){
        var myCookie = getCookie("helpText");

        if (typeof myCookie === 'undefined') {
            // close the div in 8 secs
             window.setTimeout( closeHelpDiv, 8000 );
            //setTimeout(closeHelpDiv, 2000);
        }


        function closeHelpDiv(){
            document.getElementById("helpdiv").style.display=" none";
        }

        function getCookie(name) {
            var value = "; " + document.cookie;
            var parts = value.split("; " + name + "=");
            if (parts.length == 2) return parts.pop().split(";").shift();
        }
    });
</script>

表创建

$(document).ready(function(){});