使用地图填充TableView<;字符串,Map<;字符串,字符串>&燃气轮机;JavaFX

使用地图填充TableView<;字符串,Map<;字符串,字符串>&燃气轮机;JavaFX,javafx,tableview,javafx-8,Javafx,Tableview,Javafx 8,我的大脑已经在燃烧,我找不到在JavaFX中填充TableView的正确方法。我的数据映射是map。第一个键是一个状态名,值是以键为变量,以值为变量值的映射。我需要一张像这样的桌子 | States | x | y | ... | state 1 | 5 | 6 | ... 等等 编辑:这是我最后一个只填充一列而其他列由相同数据填充的解决方案。这可以在另一个具有值的foreach中 for (TableColumn<ObservableList<String>, ?>

我的大脑已经在燃烧,我找不到在JavaFX中填充TableView的正确方法。我的数据映射是
map
。第一个键是一个状态名,值是以键为变量,以值为变量值的映射。我需要一张像这样的桌子

| States  | x | y | ... 
| state 1 | 5 | 6 | ...
等等

编辑:这是我最后一个只填充一列而其他列由相同数据填充的解决方案。这可以在另一个具有值的foreach中

for (TableColumn<ObservableList<String>, ?> column : table.getColumns()) {
            TableColumn<ObservableList<String>, String> col = (TableColumn<ObservableList<String>, String>) column;
            col.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(someValue));
        }
和getTableData():

observeList data=FXCollections.observearraylist();
for(字符串行:map.keySet()){
data.add(FXCollections.observableAryList(行));
}
返回数据;

我希望这是清楚的。。。谢谢

TableView的数据结构是一个
可观察列表
,它不同于模型的数据结构,即
映射
。因此,您需要某种方法将模型数据结构转换为可在TableView中使用的ObservableList

我可以想到以下几种方法:

  • 创建列表中的一组虚拟对象,每行一个,对应于模型中的真实项,并提供单元值工厂,动态地将所需数据从模型中拉出
  • 创建一个平行的ObservableList数据结构,并根据需要在模型和ObservableList之间同步基础数据
  • 上面的选项2是我在这里提供的示例。它是一种(模型、视图、视图模型)体系结构方法。模型是基于地图的底层结构,视图模型是由视图(即TableView)使用的可观察列表

    这是一个样本

    导入javafx.application.application;
    导入javafx.collections.*;
    导入javafx.scene.scene;
    导入javafx.scene.control.*;
    导入javafx.scene.control.cell.PropertyValueFactory;
    导入javafx.stage.stage;
    导入java.util.Map;
    导入java.util.Random;
    导入java.util.stream.collector;
    公共类StateView扩展了应用程序{
    @凌驾
    公众假期开始(阶段){
    ObservableMap状态=填充测试();
    final TableView TableView=新TableView();
    tableView.setItems(extractItems(states));
    最终TableColumn stateCol=新TableColumn(“状态”);
    final TableColumn variableCol=新的TableColumn(“变量”);
    最终表列值col=新表列(“值”);
    stateCol.setCellValueFactory(新属性ValueFactory(“stateName”);
    variableCol.setCellValueFactory(新属性ValueFactory(“variableName”));
    valueCol.setCellValueFactory(新属性ValueFactory(“variableValue”));
    tableView.getColumns().setAll(stateCol、variableCol、valueCol);
    states.addListener((MapChangeListener)更改->
    tableView.setItems(提取项(状态))
    );
    场景=新场景(tableView);
    舞台场景;
    stage.show();
    }
    私有ObservableList项目(ObservableMap状态){
    返回FXCollections.observableArrayList(
    states.keySet().stream().sorted().flatMap(状态->{
    映射变量=states.get(state);
    返回变量.keySet().stream().sorted().map(
    变量名称->{
    字符串variableValue=variables.get(variableName);
    返回新的StateItem(state、variableName、variableValue);
    }
    );
    }).collect(收集器.toList())
    );
    }
    私有静态最终随机=新随机(42);
    私有静态最终字符串[]variableNames={“红色”、“绿色”、“蓝色”、“黄色”};
    私有可观察映射填充遗嘱(){
    ObservableMap states=FXCollections.observableHashMap();
    对于(int i=0;i<5;i++){
    ObservableMap variables=FXCollections.observableHashMap();
    for(字符串variableName:variableNames){
    variableName,random.nextInt(255)+“”;
    }
    states.put(“state”+i,变量);
    }
    返回状态;
    }
    公共静态void main(字符串[]args){
    发射(args);
    }
    公共静态类StateItem{
    私有字符串stateName;
    私有字符串变量名;
    私有字符串变量值;
    public StateItem(字符串stateName、字符串variableName、字符串variableValue){
    this.stateName=stateName;
    this.variableName=variableName;
    this.variableValue=variableValue;
    }
    公共字符串getStateName(){
    返回stateName;
    }
    public void setStateName(字符串stateName){
    this.stateName=stateName;
    }
    公共字符串getVariableName(){
    返回变量名;
    }
    公共void setVariableName(字符串variableName){
    this.variableName=variableName;
    }
    公共字符串getVariableValue(){
    返回可变值;
    }
    公共void setVariableValue(字符串variableValue){
    this.variableValue=variableValue;
    }
    }
    }
    
    我要做的是提供一个新的StateItem类,它将数据馈送到视图模型的可观察列表中,并包含用于表中每一行的stateName、variableName和variableValue值。有一个单独的提取功能,用于从模型地图中提取数据,并根据需要填充视图模型可观察列表

    “按需”对你意味着什么将取决于你需要完成什么。如果您只需要在初始化时预先填充数据,那么只需调用一次即可将数据提取到视图模型

    如果需要根据对基础da的更改动态更改视图模型
    ObservableList<ObservableList<String>> tableData = FXCollections.observableArrayList();
    for (Map<String, String> map : map.values()) {
                    for (Map.Entry<String, String> entry : map.entrySet()) {
                        if (Utils.getTableColumnByName(table, entry.getKey()) != null) {
                            TableColumn<ObservableList<String>, String> column = (TableColumn<ObservableList<String>, String>) Utils.getTableColumnByName(table, entry.getKey());
                            column.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(entry.getValue()));
                        }
                    }
                }
    for (Integer stateIndex : states) {
                    tableData.add(FXCollections.observableArrayList("state " + stateIndex));
                }
    table.setItems(tableData);
    
    TableColumn<ObservableList<String>, String> varColumn = new TableColumn();
                    varColumn.setText(variable.getText());
                    varColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(value.getText()));
                    table.getColumns().add(varColumn);
    
    table.setItems(getTableData());
    
    ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
    
        for (String row : map.keySet()) {
            data.add(FXCollections.observableArrayList(row));
        }
    
        return data;
    
    import javafx.application.Application;
    import javafx.collections.*;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.stage.Stage;
    
    import java.util.Map;
    import java.util.Random;
    import java.util.stream.Collectors;
    
    public class StateView extends Application {
        @Override
        public void start(Stage stage) {
            ObservableMap<String, ObservableMap<String, String>> states = populateStates();
    
            final TableView<StateItem> tableView = new TableView<>();
            tableView.setItems(extractItems(states));
    
            final TableColumn<StateItem, String> stateCol    = new TableColumn<>("State");
            final TableColumn<StateItem, String> variableCol = new TableColumn<>("Variable");
            final TableColumn<StateItem, String> valueCol    = new TableColumn<>("Value");
    
            stateCol.setCellValueFactory(new PropertyValueFactory<>("stateName"));
            variableCol.setCellValueFactory(new PropertyValueFactory<>("variableName"));
            valueCol.setCellValueFactory(new PropertyValueFactory<>("variableValue"));
    
            tableView.getColumns().setAll(stateCol, variableCol, valueCol);
    
            states.addListener((MapChangeListener<String, ObservableMap<String, String>>) change -> 
                    tableView.setItems(extractItems(states))
            );
    
            Scene scene = new Scene(tableView);
            stage.setScene(scene);
            stage.show();
        }
    
        private ObservableList<StateItem> extractItems(ObservableMap<String, ObservableMap<String, String>> states) {
            return FXCollections.observableArrayList(
                    states.keySet().stream().sorted().flatMap(state -> {
                        Map<String, String> variables = states.get(state);
                        return variables.keySet().stream().sorted().map(
                                variableName -> {
                                    String variableValue = variables.get(variableName);
                                    return new StateItem(state, variableName, variableValue);
                                }
                        );
                    }).collect(Collectors.toList())
            );
        }
    
        private static final Random random = new Random(42);
        private static final String[] variableNames = { "red", "green", "blue", "yellow" };
    
        private ObservableMap<String, ObservableMap<String, String>> populateStates() {
            ObservableMap<String, ObservableMap<String, String>> states = FXCollections.observableHashMap();
            for (int i = 0; i < 5; i ++) {
                ObservableMap<String, String> variables = FXCollections.observableHashMap();
    
                for (String variableName: variableNames) {
                    variables.put(variableName, random.nextInt(255) + "");
                }
    
                states.put("state " + i, variables);
            }
    
            return states;
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        public static class StateItem {
            private String stateName;
            private String variableName;
            private String variableValue;
    
            public StateItem(String stateName, String variableName, String variableValue) {
                this.stateName = stateName;
                this.variableName = variableName;
                this.variableValue = variableValue;
            }
    
            public String getStateName() {
                return stateName;
            }
    
            public void setStateName(String stateName) {
                this.stateName = stateName;
            }
    
            public String getVariableName() {
                return variableName;
            }
    
            public void setVariableName(String variableName) {
                this.variableName = variableName;
            }
    
            public String getVariableValue() {
                return variableValue;
            }
    
            public void setVariableValue(String variableValue) {
                this.variableValue = variableValue;
            }
        }
    }
    
    public class Row {
    
    private String state;
    
    private String[] values;
    
    public Row(String state, String... values) {
        this.state = state;
        this.values = values;
    }
    
    public String getState() {
        return state;
    }
    
    public List<String> getValues() {
        return Arrays.asList(values);
    }
    
    column.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue().getValues().get(index)));
    
    public ObservableList<Row> getTableData() {
        ObservableList<Row> data = FXCollections.observableArrayList();
    
        for (Map.Entry<String, TreeMap<String, String>> entry : map.entrySet()) {
            String[] values = new String[entry.getValue().values().size()];
            int index = 0;
            for (String value : entry.getValue().values()) {
                values[index] = value;
                index++;
            }
            Row row = new Row(entry.getKey(), values);
            data.add(row);
        }
    
        return data;
    }
    
    table.setItems(getTableData());