2016-05-27 6 views
-1

なぜ私はテーブルに1つのコンテンツを追加する場合でも、重複した子の追加エラーが表示されている理由を理解できないようです。Javafx IllegalArgumentException:子供:重複した子が追加されました

3の主なクラスがある:

  1. WindowTease:ステージをロードしloadTable()メソッド
  2. InventoryController呼び出し:標準FXMLコントローラ、および汎用loadTable()メソッド
  3. InventoryCellを含んで私は各列にsetcellfactory()を使用します。

    によって引き起こさ

    :java.lang.IllegalArgumentExceptionが:子供:重複して子供たちは、コメントを追加しました:親=のTableRow @ 6c41701f [styleClassの=セルの索引付きセルテーブル行セル] 'NULL' ここ

である私コントローラ:

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 
} 

、最終的にはI:ここ

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); 
    } 

} 

とは、ApplicationクラスでありますnventoryCellは、テーブルセルを拡張:

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であなたのstartメソッドパス? –

+0

はい..sry私はそれを追加するのを忘れた – rjbaj

+0

通常、スニペットは十分ではありません...実際に必要なのは、問題を示すSSCCEです;-)だからちょうど推測:Component.getNode()は、シーングラフに複数回追加されますか? – kleopatra

答えて

2

これは、セル工場と呼ばれていますが、理由コンテナを細胞ではない:

TableViewはのcellFactoryを使用していますそれはTableColumnです。列のデータを表示するノードを作成します。これは、表示される行ごとに1回実行されます。あなたは今、いくつかの時点以降のTableViewSkinが最終的にレイアウトを組み立てる際に、毎回同じTableCellインスタンスを返す場合

は、このようないくつかの状況は、最終的に到達することになります。

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

はされていませんInventoryCell1はシーングラフに複数回含まれてはいけません。

したがって、ファクトリの呼び出しごとに別のTableCellインスタンスが返されていることを確認する必要があります。

param -> cellFactory 

はちょうどそれは何度も何度もloadTableメソッドに渡され、TableCellのインスタンスを返します。

あなたは簡単しかし、工場を作成することができます8つの参照をメソッドのJavaを使用して:

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

良いキャッチ+1 :-) – kleopatra

+0

これは私がファビアンを考えていたものです。ありがとう。 – rjbaj

関連する問題