Search code examples
javajavafxtableviewclone

Copying a TableView field by field (in order to modify it)


I'd like to copy a TableView cell by cell, so I can modify it later. I am stuck because I can't instantiate a TableColumn and thus don't know how to set the columns. I don't know what to do with rowHeader or how to do it differently.

public TableView<ObservableMap<String, CellDescriptor>> copyTableViewDeleteRow(int j)
{
    //FIXME
    TableView<ObservableMap<String, CellDescriptor>> tableViewCopy = new TableView<ObservableMap<String, CellDescriptor>> ();

    ObservableList<TableColumn<ObservableMap<String, CellDescriptor>, ?>> columns = tableView.getColumns();

    ObservableList<TableColumn<ObservableMap<String, CellDescriptor>, ?>> columnsNew = 
            tableViewCopy.getColumns();

    ListOrderedMap<String, CellDescriptor> rowHeader = new ListOrderedMap<>();

    int rowIndex = 0;
    int columnIndex = 0;
    for (TableColumn<?, ?> column : columns) {
        String cell = column.getText();
        String key = COLUMN_KEY_PREFIX + Integer.toString(columnIndex);
        CellDescriptor cd = new CellDescriptor(columnIndex, rowIndex, cell, this);
        rowHeader.put(key, cd);
        //TODO ? cannot instantiate TableColumn
        TableColumn<ObservableMap<String, CellDescriptor>, ?> columnNew = 
                //new TableColumn<ObservableList<String>, CellDescriptor>(key, cd);
                new TableColumn<ObservableMap<String, CellDescriptor>, ?>(cd);

        ++columnIndex;
    }

    ObservableList<ObservableMap<String, CellDescriptor>> itemsNew =
            tableViewCopy.getItems();

    ++rowIndex;
    for (Object row : tableView.getItems()) {
        ObservableMap<String, CellDescriptor> e = FXCollections.observableMap(new HashMap<String, CellDescriptor>());

        columnIndex = 0;
        for (TableColumn column : columns) {

            CellDescriptor cd = (CellDescriptor) column.getCellObservableValue(row).getValue();
            CellDescriptor cdNew = cd.clone();

            if(rowIndex == 1 && columnIndex == 1)
                cdNew.setText("xxx");

            e.put(COLUMN_KEY_PREFIX + columnIndex, cdNew);

            ++columnIndex;
        }

        itemsNew.add(e);

        ++rowIndex;
    }       

    System.out.println("tableViewCopy columns size=" + tableViewCopy.getColumns().size()); // is zero
    System.out.println("tableViewCopy items size=" + tableViewCopy.getItems().size()); // is three

    return tableViewCopy;
}

It seems I am missing the columns, since their size is zero.


Solution

  • I solved this issue by writing the rows to a data object, then used the existing function that creates a tableView from a data object. Function is as follows:

    protected TableView<ObservableMap<String, CellDescriptor>> createTableView(TableFile tableFile)
    {
        int columns = tableFile.getColumnCount();
        int rows = tableFile.getRowCount();
    
        ObservableList<ObservableMap<String, CellDescriptor>> data = FXCollections.observableArrayList();
    
        for (int i = 1; i < rows; i++)
        {
            ListOrderedMap<String, CellDescriptor> row = tableFile.getRow(i);
            ObservableMap<String, CellDescriptor> oRow = FXCollections.observableMap(row);
            data.add(oRow);
        }
    
        TableView<ObservableMap<String, CellDescriptor>> tableView = new TableView<>();
        tableView.setEditable(true);
        Callback<TableColumn<ObservableMap<String, CellDescriptor>, CellDescriptor>, TableCell<ObservableMap<String, CellDescriptor>, CellDescriptor>> cellFactory
            = (TableColumn<ObservableMap<String, CellDescriptor>, CellDescriptor> param) -> new ContextMenuCell();
        for (int i = 0; i < columns; i++)
        {
            String name = tableFile.getHeaderCell(i);
            String key = tableFile.getKey(i);
            TableColumn<ObservableMap<String, CellDescriptor>, CellDescriptor> tc = new TableColumn<>(name);
            tc.setCellValueFactory(new ObservableMapValueFactory<String, CellDescriptor>(key));
            tc.setCellFactory(cellFactory);
            tc.setOnEditCommit(
                    (TableColumn.CellEditEvent<ObservableMap<String, CellDescriptor>, CellDescriptor> event) ->
                    {
                        ObservableMap<String, CellDescriptor> map = event.getTableView().getItems().get(event.getTablePosition().getRow());
                        int ii = event.getOldValue().getI();
                        int jj = event.getOldValue().getJ();
                        String text = event.getNewValue().getText();
                        TableFile tf = event.getOldValue().getTf();
                        CellDescriptor newValue = new CellDescriptor(ii, jj, text, tf);
                        map.put(key, newValue);
                    });
            ContextMenu columnContextMenue = createColumnContextMenu(i);
            tc.setContextMenu(columnContextMenue);
            tableView.getColumns().add(tc);
        }
    
        tableView.setItems(data);
        return tableView;
    }
    

    The data object looks like this:

            ArrayList<ListOrderedMap<String, CellDescriptor>> newData = new ArrayList<>();
    

    and is filled as follows:

    public void copyTableViewDeleteRow(int j)
    {
        ArrayList<ListOrderedMap<String, CellDescriptor>> newData = new ArrayList<>();
    
        //TODO
        ObservableList<TableColumn<ObservableMap<String, CellDescriptor>, ?>> columns = tableView.getColumns();
    
        ListOrderedMap<String, CellDescriptor> rowHeader = new ListOrderedMap<>();
    
        int rowIndex = 0;
        int columnIndex = 0;
        for (TableColumn<?, ?> column : columns) {
            String cell = column.getText();
            String key = COLUMN_KEY_PREFIX + Integer.toString(columnIndex);
            CellDescriptor cd = new CellDescriptor(columnIndex, rowIndex, cell, this);
            rowHeader.put(key, cd);
    
            ++columnIndex;
        }
    
        newData.add(rowHeader);     
    
        ObservableList<ObservableMap<String, CellDescriptor>> items =
                tableViewCopy.getItems();
    
        ++rowIndex;
        for (Object row : tableView.getItems()) {
            ListOrderedMap<String, CellDescriptor> newRow = new ListOrderedMap<>();
    
            columnIndex = 0;
            for (TableColumn column : columns) {
    
                CellDescriptor cd = (CellDescriptor) column.getCellObservableValue(row).getValue();
                CellDescriptor cdNew = cd.clone();
    
                if(rowIndex == 1 && columnIndex == 1)
                    cdNew.setText("xxx");
    
                newRow.put(COLUMN_KEY_PREFIX + columnIndex, cdNew);
                ++columnIndex;
            }
    
            items.add(e);
            newData.add(newRow);
    
            ++rowIndex;
        }       
    
        this.data = newData;
    }