使用HashMap填充TableView,HashMap将在HashMap更改时更新 [英] Populating a TableView with a HashMap that will update when HashMap changes

查看:176
本文介绍了使用HashMap填充TableView,HashMap将在HashMap更改时更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我跟着这篇文章

使用tableview(JavaFX)绑定hashmap



并创建了一个由HashMap中的数据填充的TableView。



TableView HashMap 接收它的数据,称为 map 通过从 map.entrySet()创建一个 ObservableList 并处理 ObservableList 关闭到 TableView 的构造函数。 (代码如下)



然而,尽管它是 ObservableList 并且 SimpleStringProperty s,当更改基础HashMap时,TableView不会更新。

$ b

  public class MapTableView extends Application {

@Override
public void start(Stage stage)throws Exception {
try {
//示例数据
Map< String,String> map = new HashMap<>();
map.put(one,One);
map.put(two,Two);
map.put(three,Three);


//使用Map.Entry的详细类型< String,String>
TableColumn< Map.Entry< String,String>,String> column1 = new TableColumn<>(Key);
column1.setCellValueFactory(new Callback< TableColumn.CellDataFeatures< Map.Entry< String,String>,String>,ObservableValue< String>>(){

@Override
public ObservableValue< String> call(TableColumn.CellDataFeatures< Map.Entry< String,String>,String> p){
//这个回调只返回一个单元格的属性,你不能在这里使用循环
//对于第一列,我们使用键
返回新的SimpleStringProperty(p.getValue()。getKey());
}
});

TableColumn< Map.Entry< String,String>,String> column2 = new TableColumn<>(Value);
column2.setCellValueFactory(new Callback< TableColumn.CellDataFeatures< Map.Entry< String,String>,String>,ObservableValue< String>>(){

@Override
public ObservableValue< String> call(TableColumn.CellDataFeatures< Map.Entry< String,String>,String> p){
//对于第二列,我们使用值
return new SimpleStringProperty(p.getValue() .getValue());
}
});

ObservableList< Map.Entry< String,String>> items = FXCollections.observableArrayList(map.entrySet());
final TableView< Map.Entry< String,String>> table = new TableView<>(items);

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

Button changeButton = new Button(Change);
changeButton.setOnAction((ActionEvent e) - > {
map.put(two,2);
System.out.println(map);
});
VBox vBox = new VBox(8);
vBox.getChildren()。addAll(table,changeButton);

场景场景=新场景(vBox,400,400);
stage.setScene(scene);
stage.show();
} catch(Exception e){
e.printStackTrace();



public static void main(String [] args){
launch();
}

}

这正是<除了我添加了下面的按钮之外,还绑定了hashtable和tableview(JavaFX):



 按钮changeButton = new Button(Change); 
changeButton.setOnAction((ActionEvent e) - > {
map.put(two,2);
System.out.println(map);
});

然后我使用TableView添加到VBox中。



当我点击按钮时, TableView 不会更新。但是,由于 System.out.println(map)输出的不同,我可以验证底层的 HashMap 是否确实发生了变化。另外,当我点击 TableView 中的列标题以按一列对数据进行排序时,表格数据重新排序后出现新的更新值。



谢谢,



Mark

解决方案使用 ObservableMap 用监听器保持 TableView 项和映射关键字相同,并使用 cellValueFactory Bindings.valueAt ,例如:

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

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

map.addListener((MapChangeListener.Change< ;? extends String,?extends String> change) - > {
boolean removed = change.wasRemoved();
if(删除!= change.wasAdded()){
//不存在现有的键
if(removed){
keys.remove(change.getKey());
} else {
keys.add(change.getKey());
}
}
});

map.put(one,One);
map.put(two,Two);
map.put(three,Three);

最终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(cd - > Bindings.valueAt(map,cd.getValue()));

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


I have followed this post

Binding hashmap with tableview (JavaFX)

and created a TableView that is populated by data from a HashMap.

The TableView receives its data from a HashMap called map by creating an ObservableList from map.entrySet() and handing that ObservableList off to the TableView's constructor. (Code is below)

However, although it's an ObservableList with SimpleStringPropertys, the TableView does not update when changes are made to the underlying HashMap.

Here is my code:

public class MapTableView extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        try {
            // sample data
            Map<String, String> map = new HashMap<>();
            map.put("one", "One");
            map.put("two", "Two");
            map.put("three", "Three");


            // use fully detailed type for Map.Entry<String, String> 
            TableColumn<Map.Entry<String, String>, String> column1 = new TableColumn<>("Key");
            column1.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry<String, String>, String>, ObservableValue<String>>() {

                @Override
                public ObservableValue<String> call(TableColumn.CellDataFeatures<Map.Entry<String, String>, String> p) {
                    // this callback returns property for just one cell, you can't use a loop here
                    // for first column we use key
                    return new SimpleStringProperty(p.getValue().getKey());
                }
            });

            TableColumn<Map.Entry<String, String>, String> column2 = new TableColumn<>("Value");
            column2.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry<String, String>, String>, ObservableValue<String>>() {

                @Override
                public ObservableValue<String> call(TableColumn.CellDataFeatures<Map.Entry<String, String>, String> p) {
                    // for second column we use value
                    return new SimpleStringProperty(p.getValue().getValue());
                }
            });

            ObservableList<Map.Entry<String, String>> items = FXCollections.observableArrayList(map.entrySet());
            final TableView<Map.Entry<String,String>> table = new TableView<>(items);

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

            Button changeButton = new Button("Change");
            changeButton.setOnAction((ActionEvent e) -> {
                map.put("two", "2");
                System.out.println(map);
            });
            VBox vBox = new VBox(8);
            vBox.getChildren().addAll(table, changeButton);

            Scene scene = new Scene(vBox, 400, 400);
            stage.setScene(scene);
            stage.show();
        }  catch(Exception e) {
            e.printStackTrace();
        }
    } 

    public static void main(String[] args) {
        launch();
    }

}

This is exactly the code from Binding hashmap with tableview (JavaFX) except I have added the following button:

        Button changeButton = new Button("Change");
        changeButton.setOnAction((ActionEvent e) -> {
            map.put("two", "2");
            System.out.println(map);
        });

which I then add to a VBox with the TableView.

When I click the button, the TableView is not updated. However, I can verify that the underlying HashMap has indeed changed because of the System.out.println(map) output. Also when I click on a column header in the TableView to sort the data by one column, the new updated value appears after the table data is re-sorted.

How can I make the table update automatically when the underlying map is changed?

Thank you,

Mark

解决方案

Use an ObservableMap with a listener that keeps the TableView items and the keys of the map the same and use the cellValueFactory with Bindings.valueAt, e.g.:

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

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

map.addListener((MapChangeListener.Change<? extends String, ? extends String> 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("one", "One");
map.put("two", "Two");
map.put("three", "Three");

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

TableColumn<String, String> column1 = new TableColumn<>("Key");
// display item value (= constant)
column1.setCellValueFactory(cd -> Bindings.createStringBinding(() -> cd.getValue()));

TableColumn<String, String> column2 = new TableColumn<>("Value");
column2.setCellValueFactory(cd -> Bindings.valueAt(map, cd.getValue()));

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

这篇关于使用HashMap填充TableView,HashMap将在HashMap更改时更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆