javafx tableview data from List

后端 未结 2 597
情话喂你
情话喂你 2020-12-21 11:59

I\'ve got problem with TableView in JavaFX.

Creating tables from existing class with all fields defined is easy.

But I\'m wondering if it is possible to make

相关标签:
2条回答
  • 2020-12-21 12:39

    As a little piece for my work i need a TableView with dynamically filled data from a List. I looked at some other samples out there in StackOverflow and also at the Oracle tutorials. But nothing fits my needs.

    To meet my necessity i puzzled the different solutions together. See the working sample below.

    import java.util.ArrayList;
    import javafx.util.Callback;
    import javafx.util.StringConverter;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.geometry.Insets;
    import javafx.scene.paint.Color;
    import javafx.scene.text.Font;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.control.Label;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.cell.TextFieldTableCell;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.value.ObservableValue;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    import javafx.application.Application;
    
    /**
     *
     * @author Rob
     */
    public class TableViewSample extends Application {
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage stage) {
            Scene scene = new Scene(new Group());
            stage.setTitle("Table View Sample");
            stage.setWidth(400);
            stage.setHeight(500);
    
            final Label label = new Label("Student IDs");
            label.setFont(new Font("Arial", 20));
    
            TableView tableView = new TableView<>();
            tableView.setEditable(true);
            tableView.getSelectionModel().setCellSelectionEnabled(true);
    
            ObservableList<TableColumn> tableViewColumns = generateTableViewColumns();
            tableView.getColumns().setAll(tableViewColumns);
    
            ObservableList<TableColumn> tcs = tableView.getColumns();
            for (int i = 0; i < tcs.size(); i++) {
                TableColumn tc = tcs.get(i);
    
                if (i == 0) {
                    Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> cellValueFactory = buildCallbackColor(i);
                    tc.setCellValueFactory(cellValueFactory);
                } else {
                    Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> cellValueFactory = buildCallbackString(i);
                    tc.setCellValueFactory(cellValueFactory);
                }
    
            }
    
            ObservableList<ArrayList> tableViewRows = generateTableViewRows();
            tableView.getItems().setAll(tableViewRows);
    
            for (int i = 0; i < tcs.size(); i++) {
                TableColumn dataColumn = tcs.get(i);
    
                if (i == 0) {
                    Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> cellFactoryPane = buildCallbackPane();
                    dataColumn.setCellFactory(cellFactoryPane);
                } else {
                    Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> cellFactoryTextFieldTableCell = buildCallbackTextFieldTableCell();
                    dataColumn.setCellFactory(cellFactoryTextFieldTableCell);
                }
    
            }
    
            final VBox vbox = new VBox();
    
            vbox.setSpacing(5);
            vbox.setPadding(new Insets(10, 0, 0, 10));
            vbox.getChildren().addAll(label, tableView);
    
            ((Group) scene.getRoot()).getChildren().addAll(vbox);
    
            stage.setScene(scene);
    
            stage.show();
        }
    
        private ObservableList<TableColumn> generateTableViewColumns() {
            ObservableList<TableColumn> tableViewColumns = FXCollections.observableArrayList();
            TableColumn firstDataColumn = new TableColumn<>("Activity");
            TableColumn secondDataColumn = new TableColumn<>("Class A");
            TableColumn thirdDataColumn = new TableColumn<>("Class B");
    
            firstDataColumn.setMinWidth(80);
            secondDataColumn.setMinWidth(130);
            thirdDataColumn.setMinWidth(130);
    
            tableViewColumns.add(firstDataColumn);
            tableViewColumns.add(secondDataColumn);
            tableViewColumns.add(thirdDataColumn);        
    
            return tableViewColumns;
        }
    
        private ObservableList<ArrayList> generateTableViewRows() {
            int max = 6;
            ObservableList<ArrayList> tableViewRows = FXCollections.observableArrayList();
            for (int i = 1; i < max; i++) {
                ArrayList dataRow = new ArrayList<>();
    
                Color value1 = Color.GREEN;
                String value2 = "A" + i;
                String value3 = "B" + i;
    
                dataRow.add(value1);
                dataRow.add(value2);
                dataRow.add(value3);
    
                tableViewRows.add(dataRow);
            }
            return tableViewRows;
        }
    
        private Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> buildCallbackColor(int index) {
            Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>>() {
                @Override
                public ObservableValue<Color> call(TableColumn.CellDataFeatures<ArrayList, Color> param) {
                    return new SimpleObjectProperty(param.getValue().get(index));
                }
            };
            return cellValueFactory;
        }
    
        private Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> buildCallbackString(int index) {
            Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>>() {
                @Override
                public ObservableValue<String> call(TableColumn.CellDataFeatures<ArrayList, String> param) {
                    return new SimpleStringProperty((String) param.getValue().get(index));
                }
            };
            return cellValueFactory;
        }
    
        private Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> buildCallbackPane() {
            Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> cellFactory = new Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>>() {
                @Override
                public TableCell call(TableColumn tableColumn) {
                    double cellWidth = tableColumn.getMinWidth();
                    double cellHeight = 35;
    
                    TableCell tableCell = new TableCell<Object, Color>() {
                        @Override
                        protected void updateItem(Color item, boolean empty) {
                            super.updateItem(item, empty);
    
                            if (empty) {
                                setText(null);
                                setGraphic(null);
                            } else {
                                Pane p = new Pane();
                                p.setPrefSize(cellWidth, cellHeight);
                                Canvas canvasRectLayerColor = new Canvas();
                                p.getChildren().add(canvasRectLayerColor);
                                canvasRectLayerColor.setWidth(20);
                                canvasRectLayerColor.setHeight(20);
                                GraphicsContext gc = canvasRectLayerColor.getGraphicsContext2D();      
                                gc.setFill(item);
                                gc.fillRect(0, 0, canvasRectLayerColor.getWidth(), canvasRectLayerColor.getHeight());
                                setGraphic(p);
                            }
                        }
                    };
    
                    return tableCell;
                }
            };
    
            return cellFactory;
        }
    
        private Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> buildCallbackTextFieldTableCell() {
            Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> cellFactory = new Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>>() {
                @Override
                public TableCell call(TableColumn tc) {
                    TextFieldTableCell tftc = new TextFieldTableCell(new StringConverter() {
                        @Override
                        public String toString(Object t) {
                            return t.toString();
                        }
    
                        @Override
                        public Object fromString(String string) {
                            return string;
                        }
                    });
    
                    return tftc;
                }
            };
            return cellFactory;
        }
    
    }
    

    Hope this one help even it is quite late.

    0 讨论(0)
  • 2020-12-21 12:45

    You can do this by replacing String to StringProperty in the List:

    @FXML
    private TableView<List<StringProperty>> testTable;
    

    then:

    TableColumn<List<StringProperty>, String> coll = new TableColumn<>("one");
    

    add the cellValueFactories:

    col1.setCellValueFactory(data -> data.getValue().get(0));
    col2.setCellValueFactory(data -> data.getValue().get(1));
    .
    .
    

    and so on.

    This means the first element of the list will be used in col1, the second element of the list will be used in col2.

    Then you can populate the list like:

    ObservableList<List<StringProperty>> data = FXCollections.observableArrayList();
    List<StringProperty> firstRow = new ArrayList<>();
    firstRow.add(0, new SimpleStringProperty("Andrew"));
    firstRow.add(1, new SimpleStringProperty("Smith"));
    .
    .
    .
    data.add(firstRow);
    .
    .
    .
    and so on...
    table.setItems(data);
    

    It is doable this way but I would say it is a very bad practice.

    0 讨论(0)
提交回复
热议问题