2013-06-12 90 views
20

我正在嘗試使用表視圖來呈現/編輯「鍵=值」對。 所以該表應該有兩列:「關鍵」和「價值」。鍵只是一個普通的字符串,值可以是任何東西。我的問題是,值的數據類型可能因行而異。基本上,我想使用複選框布爾值和列表的選擇。我已經找到一種方法通過將細胞工廠進行與複選框或選擇整個表列:JavaFX 2 TableView:取決於單元格內數據的不同單元工廠

final TableColumn<FieldValue, Field> valueColumn = new TableColumn<>("Value"); 
valueColumn.setCellFactory(new Callback<TableColumn<FieldValue, Field>, TableCell<FieldValue, Field>>() { 
    @Override 
    public TableCell<FieldValue, Field> call(final TableColumn<FieldValue, Field> column) { 
     // if (value instanceof Boolean) 
     return new CheckBoxTableCell<>(); 
    } 
}); 

但我需要的是能夠基於項目的那將會類型插入條件在單元格內呈現。換句話說,一些細胞工廠在細胞水平上,而不是在細胞水平上。那在渲染時評估我的狀況。我還沒有找到任何解決方案。也許有人有一些適當的技術來實現這種渲染?也許一些第三方數據網格?

回答

33

這是一個顯示各種類型的字符串和對象的表格。

自定義單元工廠用於處理不同對象類型的顯示(通過對對象的類型執行實例檢查並呈現相應的文本或圖形)。

pairtable

import javafx.application.*; 
import javafx.beans.property.ReadOnlyObjectWrapper; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.*; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.image.*; 
import javafx.scene.layout.*; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.util.Pair; 

public class PairTable extends Application { 
    public static final String NAME_COLUMN_NAME = "Name"; 
    public static final String VALUE_COLUMN_NAME = "Value"; 

    final TableView<Pair<String, Object>> table = new TableView<>(); 

    public static void main(String[] args) throws Exception { 
     launch(args); 
    } 

    public void start(final Stage stage) throws Exception { 
     // model data 
     ObservableList<Pair<String, Object>> data = FXCollections.observableArrayList(
       pair("Song", "Bach Cello Suite 2"), 
       pair("Image", new Image("http://upload.wikimedia.org/wikipedia/en/9/99/Bach_Seal.jpg")), 
       pair("Rating", 4), 
       pair("Classic", true), 
       pair("Song Data", new byte[]{}) 
     ); 

     table.getItems().setAll(data); 
     table.setPrefHeight(275); 

     // table definition 
     TableColumn<Pair<String, Object>, String> nameColumn = new TableColumn<>(NAME_COLUMN_NAME); 
     nameColumn.setPrefWidth(100); 
     TableColumn<Pair<String, Object>, Object> valueColumn = new TableColumn<>(VALUE_COLUMN_NAME); 
     valueColumn.setSortable(false); 
     valueColumn.setPrefWidth(150); 

     nameColumn.setCellValueFactory(new PairKeyFactory()); 
     valueColumn.setCellValueFactory(new PairValueFactory()); 

     table.getColumns().setAll(nameColumn, valueColumn); 
     valueColumn.setCellFactory(new Callback<TableColumn<Pair<String, Object>, Object>, TableCell<Pair<String, Object>, Object>>() { 
      @Override 
      public TableCell<Pair<String, Object>, Object> call(TableColumn<Pair<String, Object>, Object> column) { 
       return new PairValueCell(); 
      } 
     }); 

     // layout the scene. 
     final StackPane layout = new StackPane(); 
     layout.getChildren().setAll(table); 
     Scene scene = new Scene(layout); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    private Pair<String, Object> pair(String name, Object value) { 
     return new Pair<>(name, value); 
    } 
} 

class PairKeyFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, String>, ObservableValue<String>> { 
    @Override 
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Pair<String, Object>, String> data) { 
     return new ReadOnlyObjectWrapper<>(data.getValue().getKey()); 
    } 
} 

class PairValueFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, Object>, ObservableValue<Object>> { 
    @SuppressWarnings("unchecked") 
    @Override 
    public ObservableValue<Object> call(TableColumn.CellDataFeatures<Pair<String, Object>, Object> data) { 
     Object value = data.getValue().getValue(); 
     return (value instanceof ObservableValue) 
       ? (ObservableValue) value 
       : new ReadOnlyObjectWrapper<>(value); 
    } 
} 

class PairValueCell extends TableCell<Pair<String, Object>, Object> { 
    @Override 
    protected void updateItem(Object item, boolean empty) { 
     super.updateItem(item, empty); 

     if (item != null) { 
      if (item instanceof String) { 
       setText((String) item); 
       setGraphic(null); 
      } else if (item instanceof Integer) { 
       setText(Integer.toString((Integer) item)); 
       setGraphic(null); 
      } else if (item instanceof Boolean) { 
       CheckBox checkBox = new CheckBox(); 
       checkBox.setSelected((boolean) item); 
       setGraphic(checkBox); 
      } else if (item instanceof Image) { 
       setText(null); 
       ImageView imageView = new ImageView((Image) item); 
       imageView.setFitWidth(100); 
       imageView.setPreserveRatio(true); 
       imageView.setSmooth(true); 
       setGraphic(imageView); 
      } else { 
       setText("N/A"); 
       setGraphic(null); 
      } 
     } else { 
      setText(null); 
      setGraphic(null); 
     } 
    } 
} 
+0

這就是我最終選擇的主題花更多一點的時間之後的事情。感謝這個答案!我不知道如果「updateItem」方法是唯一一個重寫,以獲得良好的結果,但與你的例子,它似乎工作得很好 –

+0

工程,但現在的細胞只讀...任何想法如何使他們編輯? – Eddy

+0

請以新的問題Eddy提問 – jewelsea

相關問題