2015-09-28 88 views
0

我有一个TableView,它使用MappingItem对象填充。目标是在Excel源字段与数据库字段之间创建映射。JavaFX TableView项目在UI中对表格进行更改后不会更改

在TableView中我有两列。一个是<MappingItem, String>,代表Excel头。另一个是<MappingItem, GoldplusField>,代表一个数据库字段。第二列的单元格是ComboBoxTableCell,它具有来自我的数据库的字段列表。

问题是,在更改第二列组合框中的选择后,我的选择不会更新MappingItem。我试图获取选定的单元格并提取项目,但我总是得到空引用。

这是UI: enter image description here

这是一个示例代码:

package tableviewexample; 

import javafx.application.Application; 
import javafx.beans.property.ReadOnlyObjectWrapper; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.*; 
import javafx.event.*; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.control.cell.ComboBoxTableCell; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.util.StringConverter; 

public class TableViewExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TableView<MappingItem> table = new TableView<>(); 

     // FIRST COLUMN 
     TableColumn<MappingItem, String> colA = new TableColumn<>("Excel Column");   

     colA.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<MappingItem, String>, ObservableValue<String>>() { 
      @Override 
      public ObservableValue<String> call(TableColumn.CellDataFeatures<MappingItem, String> param) { 
       return new ReadOnlyObjectWrapper(param.getValue().getExcelColumnName()); 
      }    
     }); 

     //SECOND COLUMN 
     TableColumn<MappingItem, GoldplusField> colB = new TableColumn<>("Database Field Column"); 
     colB.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<MappingItem, GoldplusField>, ObservableValue<GoldplusField>>() { 
      @Override 
      public ObservableValue<GoldplusField> call(TableColumn.CellDataFeatures<MappingItem, GoldplusField> param) { 
       return new ReadOnlyObjectWrapper(param.getValue().getGpField()); 
      }    
     }); 

     GoldplusField gp1 = new GoldplusField("T1", "fName", "First Name"); 
     GoldplusField gp2 = new GoldplusField("T1", "phn", "Phone"); 

     ObservableList<GoldplusField> fieldsList = FXCollections.observableArrayList(gp1, gp2); 
     colB.setCellFactory(ComboBoxTableCell.forTableColumn(new FieldToStringConvertor(), fieldsList));   

     colB.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<MappingItem, GoldplusField>>() { 

      public void handle(TableColumn.CellEditEvent<MappingItem, GoldplusField> e) { 

       GoldplusField gpf = colB.getCellData(table.getFocusModel().getFocusedItem()); 
       System.out.println(gpf.getGpName()); 

       MappingItem item = table.getSelectionModel().getSelectedItem(); 
       System.out.println(item.getGpField().getGpName()); 

      } 
     }); 

     table.setEditable(true); 
     table.getColumns().addAll(colA, colB); 

     MappingItem mi1 = new MappingItem("name"); 
     MappingItem mi2 = new MappingItem("phone"); 
     ObservableList<MappingItem> miList = FXCollections.observableArrayList(mi1, mi2); 

     table.setItems(miList); 

     StackPane root = new StackPane(); 
     root.getChildren().add(table); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Hello World!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 

    class FieldToStringConvertor extends StringConverter<GoldplusField> { 

     @Override 
     public String toString(GoldplusField object) { 

      if (object != null) 
       return object.getGpName(); 
      else 
       return ""; 
     } 

     @Override 
     public GoldplusField fromString(String string) { 
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
     }   
    } 

    class MappingItem { 
     private String excelColumnName; 
     private GoldplusField gpField; 

     public String getExcelColumnName() { return excelColumnName; } 

     public void setExcelColumnName(String excelColumnName) { this.excelColumnName = excelColumnName; }  

     public GoldplusField getGpField() { return gpField; } 

     public void setGpField(GoldplusField gpField) { this.gpField = gpField; } 

     public MappingItem(String columnName) { 
      this.excelColumnName= columnName; 
     }  
     public MappingItem(GoldplusField gpField) { 
      this.gpField = gpField; 
     } 
     public MappingItem(String columnName, GoldplusField gpField) { 
      this.excelColumnName = columnName; 
      this.gpField = gpField; 
     }  
    }  

    class GoldplusField { 
     private String table; 
     private String dbName; 
     private String gpName; 

     public String getDbName() { return dbName; } 

     public String getGpName() { return gpName; } 

     public String getTable() { return table; } 

     public void setDbName(String dbName) { this.dbName = dbName; } 

     public void setGpName(String gpName) { this.gpName = gpName; } 

     public void setTable(String table) { this.table = table; } 

     public GoldplusField(String table, String dbName, String gpName) { 
      this.dbName = dbName; 
      this.gpName = gpName; 
      this.table = table; 
     } 
    } 

} 
+0

您是否尝试过使用ComboBoxTableCell.forTableColumn(...) –

+0

是的。没有不同。 –

+0

你还为表列设置了setOnEditCommit(...)吗? –

回答

0

确定。如前所述,问题可能在于,这些房产不是“可写的”。

我最终将我的对象属性更改为JavaFX属性。然后,我为每个人设置了一个PropertyValueFactory并将其传递给列的CellValueFactory。

谢谢。

private void populateSourceColumnsColumn() { 

    ArrayList<MappingItem> items = new ArrayList<>(); 

    ArrayList<String> headers = SheetHelper.getTableHeadersAsString(sheet, true); 

    for (String header : headers) { 
     items.add(new MappingItem(header)); 
    } 

    ObservableList<MappingItem> itemsList = FXCollections.observableArrayList(items); 
    mappingTable.setItems(itemsList);   

    // First Column 
    PropertyValueFactory<MappingItem, String> fNameCellValueFactory = new PropertyValueFactory<>("excelColumnName"); 
    inputColumnsColumn.setCellValueFactory(fNameCellValueFactory); 

    // Second Column 
    PropertyValueFactory<MappingItem, GoldplusField> gpFieldCellValueFactory = new PropertyValueFactory<>("gpField"); 
    goldplusFieldsColumn.setCellValueFactory(gpFieldCellValueFactory); 

    GoldplusDatabase gpDb = new GoldplusDatabase(DatasourceContext.INSTANCE.getDataSource()); 
    ObservableList<GoldplusField> fieldsList = FXCollections.observableArrayList(gpDb.getContactFields()); 
    goldplusFieldsColumn.setCellFactory(ComboBoxTableCell.forTableColumn(new FieldToStringConvertor(), fieldsList));   

} 

public class MappingItem { 
    private StringProperty excelColumnName = new SimpleStringProperty(this, "excelColumnName"); 
    private ObjectProperty<GoldplusField> gpField = new SimpleObjectProperty<GoldplusField>(this, "gpField"); 

    public String getExcelColumnName() { 
     return excelColumnName.get(); 
    } 
    public void setExcelColumnName(String excelColumnName) { 
     this.excelColumnName.set(excelColumnName); 
    }  
    public StringProperty excelColumnNameProperty() { 
     return excelColumnName; 
    } 
    public GoldplusField getGpField() { 
     return gpField.get(); 
    } 
    public void setGpField(GoldplusField gpField) { 
     this.gpField.set(gpField); 
    }  
    public ObjectProperty gpFieldProperty() { 
     return this.gpField; 
    }  
    public MappingItem() { 
     super(); 
    }  
    public MappingItem(String columnName) { 
     this.excelColumnName.set(columnName); 
    }  
    public MappingItem(GoldplusField gpField) { 
     this.gpField.set(gpField); 
    } 
    public MappingItem(String columnName, GoldplusField gpField) {   
     this.excelColumnName.set(columnName); 
     this.gpField.set(gpField); 
    }  
} 

public class GoldplusField { 

    private StringProperty table = new SimpleStringProperty(this, "table"); 
    private StringProperty dbName = new SimpleStringProperty(this, "dbName"); 
    private StringProperty gpName = new SimpleStringProperty(this, "gpName"); 

    public String getDbName() { 
     return dbName.get(); 
    } 
    public String getGpName() { 
     return gpName.get(); 
    } 
    public String getTable() { 
     return table.get(); 
    } 
    public void setDbName(String dbName) { 
     this.dbName.set(dbName); 
    } 
    public void setGpName(String gpName) { 
     this.gpName.set(gpName); 
    } 
    public void setTable(String table) { 
     this.table.set(table); 
    }  
    public StringProperty tableProperty() { 
     return this.table; 
    }  
    public StringProperty gpNameProperty() { 
     return this.gpName; 
    }  
    public StringProperty dbNameProperty() { 
     return this.dbName; 
    }  
    public GoldplusField(String table, String dbName, String gpName) { 

     this.dbName.set(dbName); 
     this.gpName.set(gpName); 
     this.table.set(table); 
    } 
} 
+1

看起来很合理 - 很高兴你找到了解决方案:-) – kleopatra