How can I add rows and columns to a JavaFX 8 TableView
Asked Answered
G

2

12

I see examples on the internet for adding a row to a TableView, for example using the Person class in the Oracle documentation.

But I have a variable number of columns, so I can't bind to a Person (or any other) bean business object.

The Oracle example goes on to show how to bind columns to property names, but for that, it only shows how to add columns, but not rows.

My question is, can someone point me to a Hello, World example of dynamically adding arbitrary columns and/or rows to a JavaFX 8 TableView?

Gash answered 20/8, 2014 at 0:27 Comment(5)
How can you have a variable number of columns? It doesn't really make sense, can you provide an example/use caseArchival
I am using a TableView to store properties associated with various scopes. Each column contains a scope, and the user can add new scopes on the fly. The properties are in the rows, and the user can add new properties on the fly. I can use a different UI to define the scopes, then come back and display the table, but that is too much effort for the user.Gash
It would be (relatively) simple if all properties had the same number of scopes, but becomes messy otherwise...Archival
All properties do have the same number of scopes. Once the user adds a new scope, all of the properties for that scope are blank unless and until the user enters valuesGash
I had the same issue. See also this solution: https://mcmap.net/q/1007481/-javafx-tableview-data-from-listFreewheeling
I
16

Use a List<String> (for example) for the data type, and just set the cell value factory as a callback that indexes into the list.

For example, this will create a TableView<List<String>> that is constructed out of an arbitrary tab-delimited text file. Not all rows in the file need have the same number of elements (it will pad with blanks). (It doesn't support escaped tabs, etc):

public TableView<List<String>> readTabDelimitedFileIntoTable(Path file) throws IOException {
    TableView<List<String>> table = new TableView<>();
    Files.lines(file).map(line -> line.split("\t")).forEach(values -> {
        // Add extra columns if necessary:
        for (int i = table.getColumns().size(); i < values.length; i++) {
            TableColumn<List<String>, String> col = new TableColumn<>("Column "+(i+1));
            col.setMinWidth(80);
            final int colIndex = i ;
            col.setCellValueFactory(data -> {
                List<String> rowValues = data.getValue();
                String cellValue ;
                if (colIndex < rowValues.size()) {
                    cellValue = rowValues.get(colIndex);
                } else {
                     cellValue = "" ;
                }
                return new ReadOnlyStringWrapper(cellValue);
            });
            table.getColumns().add(col);
        }

        // add row:
        table.getItems().add(Arrays.asList(values));
    });
    return table ;
}
Infancy answered 20/8, 2014 at 2:3 Comment(0)
G
9

Kind of clunky, but this sample code seems to work:

    TableView table = new TableView<>();
    private char nextChar = 'A';

    private void addColumn(TableView table) {
      String mapChar = String.valueOf(nextChar++);
      TableColumn<Map, String> column = new TableColumn<>("Class " + mapChar);
      column.setCellValueFactory(new MapValueFactory(mapChar));
      column.setMinWidth(130);
      column.setCellFactory(cellFactoryForMap);
      table.getColumns().add(column);
    }

    private void addRow(TableView table) {
      ObservableList<Map> allData = table.getItems();
      int offset = allData.size();
      Map<String, String> dataRow = new HashMap<>();
      for (int j = 0; j < table.getColumns().size(); j++) {
        String mapKey = Character.toString((char) ('A' + j));
        String value1 = mapKey + (offset + 1);
        dataRow.put(mapKey, value1);
      }
      allData.add(dataRow);
    }
  }
Gash answered 20/8, 2014 at 1:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.