2015-09-28 64 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