This discussion is archived
7 Replies Latest reply: Oct 3, 2013 8:14 PM by TranQuocUng RSS

How to edit data with dynamic TableView with dynamic column in JAVAFX

TranQuocUng Newbie
Currently Being Moderated

Today This is the demo to show data from CSV for DAT file without make custom class on tableView in JavaFX 2.0. I call this TableView as Dynamic TableView because the tableview automatically manages the columns and rows.
On my research about the editable on tableView we must have a custom class and implement it to tableView to show as this demo ==> http://docs.oracle.com/javafx/2/ui_controls/table-view.htm

But in this case I can not do it because we don't know how many column example with csv file or .dat file.... I want to do editable on this tableView in this case by add TextField into TableCell. How does it do without make custom class (because you do not how many column ...), and if it must make custom class then how about the design of custom class for this case?

Could you please help me?

This is the code demo to show your csv file or dat file into TableView

private void getDataDetailWithDynamic() {
  tblView
.getItems().clear();
  tblView
.getColumns().clear();
  tblView
.setPlaceholder(new Label("Loading..."));
  
// @Override



  
try {
       
File aFile = new File(txtFilePath.getText());
       
InputStream is = new BufferedInputStream(new FileInputStream(aFile));
       
Reader reader = new InputStreamReader(is, "UTF-8");

       
BufferedReader in = new BufferedReader(reader);

       
final String headerLine = in.readLine();
       
final String[] headerValues = headerLine.split("\t");
       
for (int column = 0; column < headerValues.length; column++) {
             tblView
.getColumns().add(
             createColumn
(column, headerValues[column]));
       
}

       
// Data:

       
String dataLine;
       
while ((dataLine = in.readLine()) != null) {
            
final String[] dataValues = dataLine.split("\t");
            
// Add additional columns if necessary:
            
for (int columnIndex = tblView.getColumns().size(); columnIndex < dataValues.length; columnIndex++) {
                  tblView
.getColumns().add(createColumn(columnIndex, ""));
            
}
            
// Add data to table:
            
ObservableList<StringProperty> data = FXCollections.observableArrayList();
            
for (String value : dataValues) {
                 data
.add(new SimpleStringProperty(value));
            
}
             tblView
.getItems().add(data);
       
}
  
} catch (Exception ex) {
       
System.out.println("ex: " + ex.toString());
  
}


  
for(int i=0; i<tblView.getColumns().size(); i++) {
       
TableColumn col = (TableColumn)tblView.getColumns().get(i);
       col
.setPrefWidth(70);
  
}
}

private TableColumn createColumn(
  
final int columnIndex, String columnTitle) {
       
TableColumn column = new TableColumn(DefaultVars.BLANK_CHARACTER);
       
String title;
       
if (columnTitle == null || columnTitle.trim().length() == 0) {
            title
= "Column " + (columnIndex + 1);
       
} else {
            title
= columnTitle;
       
}


       
Callback<TableColumn, TableCell> cellFactory = new Callback<TableColumn, TableCell>() {
       
@Override
       
public TableCell call(TableColumn p) {

            
System.out.println("event cell");
            
EditingCellData cellExtend = new EditingCellData();
            
return cellExtend;
       
}
  
};

  column
.setText(title);
  column
.setCellValueFactory(cellFactory);
  
return column;
}


Thanks for your reading.

  • 1. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    James_D Guru
    Currently Being Moderated

    See this thread: Re: Creating columns dynamically

     

    That example is not editable, but to make it so, just add something like

        column.setCellFactory(TextFieldTableCell.<ObservableList<StringProperty>>forTableColumn());
    

    to the createTableColumn(...) method.

     

    Incidentally, where did you get the code you pasted into your post? It looks kind of similar to my previous post .

     

    Message was edited by: James_D

  • 2. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    TranQuocUng Newbie
    Currently Being Moderated

    Yes, that's a good solution, I've tested and it run now. But how to commit it when I leave mouse out of cell?

    I think I must add some things like :

          column.setCellFactory(TextFieldTableCell.<ObservableList<StringProperty>>forTableColumn());

     

    I think we must add this? Is it right?

         .========================================================================>

         column.setOnEditCommit(

                    new EventHandler<TableColumn.CellEditEvent<??????, String>>() {

                        @Override

                        public void handle(TableColumn.CellEditEvent<???????????, String> t) {

                            ((TemplateDataMulticolumn) t.getTableView().getItems().get(

                                    t.getTablePosition().getRow())

                            ).set????(t.getNewValue());

                        }

                    }

            );

         <=========================================================================

    How about add it with TextFieldTableCell in the commit event?

     

    Beside it, I'm very sorry with this code. Actually I researched and see your link https://forums.oracle.com/message/10731570#10731570.

    And then I use it for this demo.

    I'm very sorry about that, James_D.

     

    Thank you.

  • 3. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    James_D Guru
    Currently Being Moderated

    Yes, that's a good solution, I've tested and it run now. But how to commit it when I leave mouse out of cell?

    I think I must add some things like :

          column.setCellFactory(TextFieldTableCell.<ObservableList<StringProperty>>forTableColumn());

    This will commit the changes to the property automatically: in other words the value of the corresponding property will be updated. Try this:

     

        Button dumpFirstRowButton = new Button("Show first row");
        dumpFirstRowButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                for (StringProperty sp : table.getItems().get(0)) {
                    System.out.print(sp.get()+"\t");
                }
                System.out.println();
            }
        });

     

    Add the button to the UI somewhere. Then load a file, edit the first row of the table, and press the button. You'll see the edited values displayed in the console.

    Obviously this won't update your file: you'll need a "save" button whose handler can iterate through the rows in the table and generate the output to the file.

     

    Beside it, I'm very sorry with this code. Actually I researched and see your link https://forums.oracle.com/message/10731570#10731570.

    And then I use it for this demo.

    Not a problem at all. I post code with the intention people should use it and learn from it.

  • 4. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    TranQuocUng Newbie
    Currently Being Moderated

    Hi, I've tried it and it isn't conmited automatically...

    This is my function create column

     

    private TableColumn createColumn(

                final int columnIndex, String columnTitle) {

            TableColumn column = new TableColumn(DefaultVars.BLANK_CHARACTER);

            String title;

            if (columnTitle == null || columnTitle.trim().length() == 0) {

                title = "Column " + (columnIndex + 1);

            } else {

                title = columnTitle;

            }

     

     

            Callback<TableColumn.CellDataFeatures<ObservableList<StringProperty>, String>,

                ObservableValue<String>> cellFactory =

                new Callback <TableColumn.CellDataFeatures<ObservableList<StringProperty>, String>,

                        ObservableValue<String>>() {

                    @Override

                    public ObservableValue<String> call(

                            TableColumn.CellDataFeatures<ObservableList<StringProperty>, String> cellDataFeatures) {

     

     

                        ObservableList<StringProperty> values = cellDataFeatures.getValue();

     

     

                        if (columnIndex >= values.size()) {

                            return new SimpleStringProperty("");

                        } else {

                            return cellDataFeatures.getValue().get(columnIndex);

                        }

                    }

                };

     

     

            column.setText(title);

            column.setId("content");

            column.setCellFactory(TextFieldTableCell.<ObservableList<StringProperty>>forTableColumn());

            column.setCellValueFactory(cellFactory);

            return column;

        }

  • 6. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    James_D Guru
    Currently Being Moderated

    Ah, may have been a small bug if your table is not rectangular (subsequent rows have more columns than the row you are editing). I pushed an update to the github link above.

  • 7. Re: How to edit data with dynamic TableView with dynamic column in JAVAFX
    TranQuocUng Newbie
    Currently Being Moderated

    Hi James_D

     

    I'm really thank you about that. This is the exactly what I need.

     

    Beside it, you have best solution for me to improve this demo.

    https://forums.oracle.com/message/11102124#11102124

     

    Because I want to make new TextFieldTableCell like with link above :

    1. private void installCustomTextFieldCellFactory(TableColumn<Player, String> column) { 
    2.     column.setCellFactory(new Callback<TableColumn<Player, String>, TableCell<Player, String>>() { 
    3.       @Override 
    4.       public TableCell<Player, String> call(TableColumn<Player, String> column) { 
    5.         return new StyledTextFieldTableCell(); 
    6.       } 
    7.        
    8.     }); 
    9.   } 

     

                   private static class StyledTextFieldTableCell extends TextFieldTableCell<Player, String> { 

                        ............................    

                   }

     

    I only change the argument with like that

     

         class EditingCellDataWithMultiColumns extends TextFieldTableCell<ObservableList<StringProperty>, String> {

              ................

         }

     

    and I add it with like :

     

         column.setCellFactory(

                    new Callback<TableColumn<ObservableList<StringProperty>, String>,

                                 TableCell<ObservableList<StringProperty>, String>>() {

                        @Override

                        public TableCell<ObservableList<StringProperty>, String> call(TableColumn<ObservableList<StringProperty>, String> column) {

                            return new EditingCellDataWithMultiColumns();

                        }

     

     

                    }

            );

     

    It's absolute perfectly.

     

    Thank you very much James.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points