2013-06-12 12 views
20

Próbuję użyć widoku tabeli do renderowania/edycji par "key = value". Zatem tabela powinna mieć dwie kolumny: "klucz" i "wartość". Klucz jest zwykłym łańcuchem, a wartość może być dowolna. Mój problem polega na tym, że typ danych wartości może się różnić od wiersza. Zasadniczo chciałem użyć pól wyboru dla wartości logicznych i wyborów dla list. Znalazłem sposób, aby uczynić całą kolumnę tabeli z wyboru lub wyboru przez ustawienie fabryki komórek:JavaFX 2 TableView: inna fabryka komórek w zależności od danych wewnątrz komórki

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

Ale to, co jest mi potrzebne, aby móc wstawić warunek na podstawie typu elementu, który ma być renderowane wewnątrz komórki. Innymi słowy, niektóre fabryki komórek na poziomie komórki, a nie na poziomie kolumny. I to ocenia mój stan w czasie renderowania. Nie znalazłem jeszcze żadnego rozwiązania tego problemu. Może ktoś ma odpowiednie techniki do realizacji tego rodzaju renderowania? Może jakiś datagrid trzeciej strony?

Odpowiedz

33

Oto tabela z parami ciągów i obiektów różnych typów.

Niestandardowa fabryka komórek służy do obsługi wyświetlania różnych typów obiektów (wykonując sprawdzenie instancji na typie obiektu i renderując odpowiedni tekst lub grafikę).

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

To co w końcu zdecydował się na to po spędzeniu trochę więcej czasu na ten temat. Dzięki za tę odpowiedź! Nie byłem pewien, czy metoda "updateItem" była jedyną, która zastąpiła, aby uzyskać dobry wynik, ale z twoim przykładem wydaje się działać dobrze –

+0

Działa, ale teraz komórki są tylko do odczytu ... każdy pomysł, jak je zrobić edytowalne? – Eddy

+0

Proszę zadać jako nowe pytanie Eddy – jewelsea