JavaFX 8 : Iterate through TableView cells and get

2019-07-20 04:13发布

问题:

I'm having troubles accessing the objects displayed in the TableColumn

Here's the code snippet where I set the graphics of one Column. Only want to show the Name of the Person object: (Any better/easier way in doing that is welcome)

ownerColumn
            .setCellFactory(new Callback<TableColumn<Site, Person>, TableCell<Site, Person>>() {

                @Override
                public TableCell<Site, Person> call(
                        TableColumn<Site, Person> param) {

                    TableCell<Site, Person> ownerCell = new TableCell<Site, Person>() {

                        @Override
                        protected void updateItem(Person item, boolean empty) {
                            if (item != null) {
                                Label label = new Label(item.getName());
                                setGraphic(label);
                            }
                        }
                    };
                    return ownerCell;
                }
            });

Now I'm trying to loop through the rows and columns go get every cell to generate a report at the end, reflecting the displayed text/graphics in the Tableview. Like this

for (Object r : this.tableview.getItems()) {
        for (Object c : this.tableview.getColumns()) {
            javafx.scene.control.TableColumn column = (javafx.scene.control.TableColumn) c;

            if (column.getCellData(r) != null) {
                // I get the object bound to the cell here, but I only want
                // to have what i've set as graphics - what the user sees on UI
                // How to use getGraphics() ?
            }
        }
    }

So the question is, how do I get the getGraphics() I've set in the CellFactory?

回答1:

A static method for any type of cell content.

Method getItems() gets the value of the property items. Property is the underlying data model for the TableView. Note that it has a generic type that must match the type of the TableView itself.

  private static ArrayList<String> getTableViewValues(TableView tableView) {
    ArrayList<String> values = new ArrayList<>();
    ObservableList<TableColumn> columns = tableView.getColumns();

    for (Object row : tableView.getItems()) {
      for (TableColumn column : columns) {
        values.add(
          (String) column.
          getCellObservableValue(row).
          getValue());
      }
    }

    return values;
  }


回答2:

This approach, accessing the Cell, will not work, as the CellFactory will not be used to produce a 1:1 Cell for each row. The Cell is only used as a lightweight View generator and will be reused heavily.

By the way you might use:

@Override
protected void updateItem(Person item, boolean empty) {
    super.updateItem(item, empty);
    if (item != null && !empty) {
        setText(item.getName());
    } else {
        setText(null);
    }
}

will simply show a text.

a) Check also the boolean empty

b) Explicitely clear all graphic/text that will be set (test here) due to the reuse cases!

c) Always call the super udateItem() method.



回答3:

As Jens-Peter says, there isn't a 1-1 correspondence between cells and items in the table, so the approach of getting the cell will not work.

You should think of table.getItems() as having the data that's displayed. The table, table columns, and table cells are just visualizations of those data. Refer back to the actual data, not to the specific visualization of it:

for (Site site : tableView.getItems()) {
    // owner column data:
    Person owner = site.getOwner();
    String ownerName = owner.getName();
    // ...
}