Abiodun Osinaike
Abiodun Osinaike

Reputation: 193

Populate tableview with two dimensional array

Am new to Javafx and wondering how to populate a tableview from a 2-dimensional array of String:

    String[][] staffArray = (String[][]) connection.getAll("StaffServices");
    ObservableList row = FXCollections.observableArrayList(staffArray);

    //don't know what should go in here

    staffTable.setItems(row);

would really appreciate a response.

Upvotes: 6

Views: 16756

Answers (3)

Nikita Ponomar
Nikita Ponomar

Reputation: 1

Additionally to answer of Brian, I added proper CellFactory, to avoid using toString() method, when we are going to view results with good design. My solution is OK, when you are using Model - View - Controller model. Here is the code for Controller block:

@FXML
private TableView<String[]> table = new TableView<>();

@FXML
public void initialize() {


    //binding our ObservableList with TableView
    String[][] staffArray = {{"a", "b", "c"},
                             {"d", "e", "f"}};
    ObservableList<String[]> data = FXCollections.observableArrayList();
    data.addAll(Arrays.asList(staffArray));

    for (int i = 0; i < data.get(0).length; i++) {
        TableColumn tc = new TableColumn();
        tc.setSortable(false);


        final int colNo = i;
        tc.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<String[], String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<String[], String> p) {
                return new SimpleStringProperty((p.getValue()[colNo]));
            }
        });
        tc.setCellFactory(col -> {
            TableCell<String[], String> cell = new TableCell<>();

            cell.itemProperty().addListener((observableValue, o, newValue) -> {
                if (newValue != null) {
                    Node graphic = createPriorityGraphic(newValue);
                    cell.graphicProperty().bind(Bindings.when(cell.emptyProperty()).then((Node) null).otherwise(graphic));
                }
            });
            return cell;
        });

        table.getColumns().add(tc);
    }


    // making Headers of table hidden
    table.widthProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
            // Get the table header
            Pane header = (Pane) table.lookup("TableHeaderRow");
            if (header != null && header.isVisible()) {
                header.setMaxHeight(0);
                header.setMinHeight(0);
                header.setPrefHeight(0);
                header.setVisible(false);
                header.setManaged(false);
            }
        }
    });

    table.setItems(data);

    table.setSelectionModel(null);

    table.setMaxSize(315.0, 502.0);

}

//prepare some special design for tableview output, if needed
@FXML
private Node createPriorityGraphic(String value) {
    if (!value.equals("0") && value != "") {
        Rectangle graphic = new Rectangle();
        graphic.setHeight(25);
        graphic.setWidth(25);
        graphic.setOpacity(80);
        return graphic;
    }
    return null;
}

Upvotes: -1

brian
brian

Reputation: 10969

I think JavaFX should have a method that just takes 2d arrays and makes tables but it's not that hard to make. The trick is to use the CellValueFactory to get the right array index for each column instead of getting a bean. This is similar to code I use.

import java.util.Arrays;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TableViewSample extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        String[][] staffArray = {{"nice to ", "have", "titles"},
                                 {"a", "b", "c"},
                                 {"d", "e", "f"}};
        ObservableList<String[]> data = FXCollections.observableArrayList();
        data.addAll(Arrays.asList(staffArray));
        data.remove(0);//remove titles from data
        TableView<String[]> table = new TableView<>();
        for (int i = 0; i < staffArray[0].length; i++) {
            TableColumn tc = new TableColumn(staffArray[0][i]);
            final int colNo = i;
            tc.setCellValueFactory(new Callback<CellDataFeatures<String[], String>, ObservableValue<String>>() {
                @Override
                public ObservableValue<String> call(CellDataFeatures<String[], String> p) {
                    return new SimpleStringProperty((p.getValue()[colNo]));
                }
            });
            tc.setPrefWidth(90);
            table.getColumns().add(tc);
        }
        table.setItems(data);
        root.getChildren().add(table);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

Upvotes: 16

Alexandre
Alexandre

Reputation: 4602

Best practices for TableView in JavaFX are to use Objects with Properties and bind them to Columns.

I would suggest moving on or converting your 2 dimensional array to a more Strongly Typed model.

What you are aiming for is to have a ObservableList<Model> that you can then assign to your TableView.

Oracle has a really good introduction to the TableView that show cases the recommendations I suggested.

Upvotes: 4

Related Questions