2013-06-12 11 views
20

Sto cercando di utilizzare la vista tabella per rendere/modificare le coppie "chiave = valore". Quindi la tabella dovrebbe avere due colonne: "chiave" e "valore". La chiave è solo una stringa normale e il valore può essere qualsiasi cosa. Il mio problema è che il tipo di dati dei valori può essere diverso da una riga all'altra. Fondamentalmente, volevo usare le checkbox per i valori booleani e le scelte per gli elenchi. Ho trovato un modo per rendere la colonna della tabella intera con le caselle di controllo o scelte impostando la fabbrica di cellule:JavaFX 2 TableView: fabbrica di celle diverse a seconda dei dati all'interno della cella

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

Ma quello che ho bisogno è di essere in grado di inserire una condizione in base al tipo di elemento che sta succedendo da rendere all'interno della cella. In altre parole, alcune celle di fabbrica a livello di cella e non a livello di colonna. E questo valuta la mia condizione al momento del rendering. Non ho ancora trovato alcuna soluzione a questo. Forse qualcuno ha delle tecniche adeguate per implementare questo tipo di rendering? Forse qualche datagrid di terze parti?

risposta

33

Ecco una tabella che mostra coppie di stringhe e oggetti di vario tipo.

Una fabbrica cellulare personalizzato viene utilizzato per gestire la visualizzazione di diversi tipi di oggetti (eseguendo un controllo instanceof sul tipo di oggetto e il rendering del testo o la grafica appropriata).

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

Questo è quello che finalmente scelto di fare dopo aver trascorso un po 'più di tempo su questo argomento. Grazie per questa risposta! Non ero sicuro che il metodo "updateItem" fosse l'unico a sovrascrivere per ottenere un buon risultato, ma con il tuo esempio sembra funzionare bene –

+0

Works ma ora le celle sono di sola lettura ... qualsiasi idea su come realizzarle modificabile? – Eddy

+0

Si prega di chiedere come una nuova domanda Eddy – jewelsea

Problemi correlati