2016-05-27 32 views
-1

我似乎無法弄清楚爲什麼重複的子項添加錯誤顯示即使我只向表中添加一個內容。Javafx IllegalArgumentException:子項:添加重複的子項

有3種主要類型:

  1. WindowTease:它加載階段,並調用可裝入()方法
  2. InventoryController:標準FXML控制器,幷包含通用可裝入()方法
  3. InventoryCell :我使用setcellfactory()爲每列。

    產生的原因:java.lang.IllegalArgumentException異常:兒童:兒童重複說:父= @的TableRow 6c41701f [=的styleClass索引細胞 - 細胞表 - 行 - 單元格] '空'

這裏是我的控制器:

public class InventoryController { 

    @FXML protected TableView mainTable; 

    public <U> void loadTable(TableCell<U, Component> cellFactory){ 

    mainTable.getColumns().clear(); 

    final String[] propertyName = {"id", "invCategory", "quantity", "description", "perItem", "icon"}; 
    final String[] columnName = {"ID", "Category", "Quantity", "Description", "Price (Per Item)", "Process"}; 

    for (int i = 0; i < propertyName.length; i++) { 
     TableColumn<U, Component> column = new TableColumn<>(columnName[i]); 
     column.setCellValueFactory(new PropertyValueFactory<>(propertyName[i])); 
     column.setCellFactory(param -> cellFactory); //this is the culprit 
     //column.setCellFactory(param -> new InventoryCell()); //this shows with no problem 
     mainTable.getColumns().add(column); 
    } 

    ObservableList<Inventory> items = FXCollections.observableArrayList(); 
    mainTable.getItems().clear(); 

    for (int i = 0; i < 1; i++) { 
     Inventory inve = new Inventory(
       new ID("WSS", i), new Describer("Click me !!"), 
       new PercentQuantity(i, 100), new Describer("Click me !!"), new Price(Currency.CHINESE_YEN, i*1000.00), 
       new HoverIcon("images/assignment_returned.png")); 
     mainTable.getItems().add(inve); 
    } 

} 

,這裏是應用程序類:

public class WindowTease extends Application { 

    @Override 
    private void start(Stage primaryStage) throws Exception { 
    FXMLLoader loader = new FXMLLoader()); 
    loader.setLocation(WindowTease.class.getResource("/layouts/inventory.fxml")); 
    InventoryController controller = new InventoryController(); 
    loader.setController(controller); 
    Parent root = loader.load(); 
    Scene scene = new Scene(root); 

    controller.loadTable(new InventoryCell()); 

    primaryStage.setScene(scene); 
    primaryStage.show();   //Caused by: java.lang.RuntimeException: Exception in Application start method 
} 

最後是我nventoryCell擴展的TableCell:

public class InventoryCell extends TableCell<Inventory, Component>{ 

    @Override 
    protected void updateItem(Component item, boolean empty) { 
     if (item == null || empty) return; 
     super.updateItem(item, empty); 
     Object node = item.getNode(); 
     if (node instanceof Node) { 
      Node graphix = ((Node)node); 
      HBox box = new HBox(graphix); 
      setText(""); 
      setGraphic(box); 

     } else if (node instanceof String) { 
      setText((String)node); 
      setGraphic(null); 
     } 
    } 
} 

更新: 罪魁禍首肯定是tablecolumn.setCellFactory(cellfactory);

+0

是否在primaryStage你的啓動方法通行證? –

+0

是的..sry我忘了補充一點,雖然通常複製 – rjbaj

+0

,片段不夠好......真正需要的是一個證明問題的SSCCE ;-)所以只是猜測:Component.getNode()可能是罪魁禍首,那就是節點多次添加到場景圖中? – kleopatra

回答

2

這就是所謂的細胞,不是細胞集裝箱是有原因的:

TableView使用的cellFactory它是TableColumn s創建節點以顯示列的數據。每行顯示一次。

如果你現在每次返回相同的TableCell例如,在某些時候,當TableViewSkin最後組裝佈局後,一些像這樣的情況下,最終將達到:

SomeParent 
    | 
    |--TableRow1 
    |  | 
    |  |--InventoryCell1 
    | 
    |--TableRow2 
      | 
      |--InventoryCell1 

這是不是允許,因爲InventoryCell1在場景圖中不得包含多次。

因此,您必須確保爲工廠的每次調用返回不同的TableCell實例。

param -> cellFactory 

將剛剛返回TableCell實例,就是一遍遍傳遞給loadTable方法。

使用方法的Java 8個引用您可以輕鬆地創建但是工廠:

public <U> void loadTable(Supplier<TableCell<U, Component>> cellFactory){ 
    ... 
    column.setCellFactory(param -> cellFactory.get()); 
controller.loadTable(InventoryCell::new); 
+0

好的捕獲+1 :-) – kleopatra

+0

這就是我在想的fabian。謝謝。 – rjbaj