Ajitkumar Patil
Ajitkumar Patil

Reputation: 79

JavaFX tableview fill the values in nested columns which are created dynamically

I am stuck with one point in JAVAFX tableview in one of our javaFX application.I am using one table view to show some data. In that tableView one of the column have nested columns under it. These nested columns I am creating from one of the list. Now here I am putting my scenario with one example. Now here I have two columns in tableView. Name and Skillset. The skill set column have two nested columns under it. I am reading the nested column names from nestedColumnsNameList. I am trying to fill the values in these nested columns from a list skillList, which has two values [Java, Dot Net]. Now every time I try to fill the values in these nested columns from a skillList, for every row I am getting same value as Dot Net in each nested columns. Below is my code:

    package demo.tableView;


import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class UpdateTableViewDynamicColumns extends Application {

    private TextField firtNameField = new TextField();
    private TextField lastNameField = new TextField();
    private TextField emailField = new TextField();
    private TextField speedField = new TextField();
    private TextField stopspeedField = new TextField();
    private Stage editView;
    private Person fPerson;
    TableView<Person> table = new TableView<Person>();;
    public static class Person {

       private String name;
        private String skillset;
        private String skills;
        /**
         * @return the firstName

        /**
         * @return the skills
         */
        public String getSkills() {
            return skills;
        }
        /**
         * @param skills the skills to set
         */
        public void setSkills(String skills) {
            this.skills = skills;
        }
        /**
         * @return the skillset
         */
        public String getSkillset() {
            return skillset;
        }
        /**
         * @param skillset the skillset to set
         */
        public void setSkillset(String skillset) {
            this.skillset = skillset;
        }
        /**
         * @return the name
         */
        public String getName() {
            return name;
        }
        /**
         * @param name the name to set
         */
        public void setName(String name) {
            this.name = name;
        }


  }

    private final ObservableList<Person> data =
            FXCollections.observableArrayList();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(535);
        stage.setHeight(535);
        editView = new Stage();

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        TableColumn firstNameCol = new TableColumn("Name");
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("name"));
        firstNameCol.setMinWidth(150);


        /*
         * this list contains the names of nested columns
         */
        List<String> nestedColumnsNameList = new ArrayList<String>();
        nestedColumnsNameList.add("Skill 1");
        nestedColumnsNameList.add("Skill 2");


        TableColumn skillSetCol = new TableColumn("Skillset");
        skillSetCol.setMinWidth(200);
        skillSetCol.setCellValueFactory(new PropertyValueFactory<Person, String>("skillset"));


        for(int i=0;i<nestedColumnsNameList.size();i++){
            TableColumn ageValCol = new TableColumn(nestedColumnsNameList.get(i));
            ageValCol.setCellValueFactory(new PropertyValueFactory<Person, String>("skills"));
            skillSetCol.getColumns().add(ageValCol);
        }

        int count = 3;

        List<String> nameList = new ArrayList<String>();
        nameList.add("Ajit Patil");
        nameList.add("Ketan Mehta");
        nameList.add("Jacob George");

        /*
         * the below list values will be set in skill columns skill1 , skill2 
         */
        List<String> skillList = new ArrayList<String>();
        skillList.add("Java");
        skillList.add("Dot net");

       for(int i=0; i<nameList.size(); i++){
            Person p =  new Person();
            p.setName(nameList.get(i));

            for(int x=0; x<skillList.size();x++){
                p.setSkills(skillList.get(x));
            }
            data.add(p);
        }
        table.setItems(data);
        table.getColumns().addAll(firstNameCol, skillSetCol);
//--- create a edit button and a editPane to edit person   
        Button addButton = new Button("Add");
        addButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                fPerson = null;
                firtNameField.setText("");
                lastNameField.setText("");
                emailField.setText("");
                editView.show();
            }
        });
        Button editButton = new Button("Edit");
        editButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                /*if (table.getSelectionModel().getSelectedItem() != null) {
                    fPerson = table.getSelectionModel().getSelectedItem();
                    firtNameField.setText(fPerson.getFirstName());
                    lastNameField.setText(fPerson.getLastName());
                    emailField.setText(fPerson.getEmail());
                    editView.show();
                }*/
            }
        });
        Button deleteButton = new Button("Delete");
        deleteButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                if (table.getSelectionModel().getSelectedItem() != null) {
                    data.remove(table.getSelectionModel().getSelectedItem());
                }
            }
        });
        Button setButton = new Button("Set");
        setButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

                Stage primaryStage = new Stage();
                Spinner<Double> dspinner = new Spinner<>();
                dspinner.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, Double.MAX_VALUE, 0.0, 1));
                dspinner.setMaxWidth(60);
                Button setButton = new Button("Set");
                setButton.setMinWidth(50);
                GridPane grid = new GridPane();
                grid.setHgap(10);
                grid.setVgap(10);
                grid.setPadding(new Insets(10));

                grid.add(new Label("Set default speed [knots] : "), 0, 1);
                grid.add(dspinner, 1, 1);
                grid.add(setButton, 2, 1);

                Scene scene = new Scene(grid, 300, 80);
                primaryStage.setTitle("Set Default value for speed");
                primaryStage.setScene(scene);
                primaryStage.initModality(Modality.APPLICATION_MODAL);
                primaryStage.show();

                setButton.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent actionEvent) {
                        try {
                            setDefaultSpeed(dspinner);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }

                    private void setDefaultSpeed(Spinner<Double> dspinner) {
                        // TODO Auto-generated method stub

                    }
                });


            }
        });
        HBox addEditDeleteButtonBox = new HBox();
        addEditDeleteButtonBox.getChildren().addAll(addButton, editButton, deleteButton,setButton);
        addEditDeleteButtonBox.setAlignment(Pos.CENTER_RIGHT);
        addEditDeleteButtonBox.setSpacing(3);

        GridPane editPane = new GridPane();
        editPane.getStyleClass().add("editView");
        editPane.setPadding(new Insets(3));
        editPane.setHgap(5);
        editPane.setVgap(5);
        Label personLbl = new Label("Person:");
        editPane.add(personLbl, 0, 1);
        GridPane.setHalignment(personLbl, HPos.LEFT);

        firtNameField.setPrefWidth(250);
        lastNameField.setPrefWidth(250);
        emailField.setPrefWidth(250);
        Label firstNameLabel = new Label("First Name:");
        Label lastNameLabel = new Label("Last Name:");
        Label emailLabel = new Label("Email:");
        Label speedLabel = new Label("Start Speed:");
        Label speedLabel1 = new Label("stop Speed:");
        editPane.add(firstNameLabel, 0, 3);
        editPane.add(firtNameField, 1, 3);
        editPane.add(lastNameLabel, 0, 4);
        editPane.add(lastNameField, 1, 4);
        editPane.add(emailLabel, 0, 5);
        editPane.add(emailField, 1, 5);
        editPane.add(speedLabel, 0, 6);
        editPane.add(speedField, 1, 6);
        editPane.add(speedLabel1, 0, 7);
        editPane.add(stopspeedField, 1, 7);
        GridPane.setHalignment(firstNameLabel, HPos.RIGHT);
        GridPane.setHalignment(lastNameLabel, HPos.RIGHT);
        GridPane.setHalignment(emailLabel, HPos.RIGHT);
        GridPane.setHalignment(speedLabel, HPos.RIGHT);

        Button saveButton = new Button("Save");
        saveButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                if (fPerson == null) {
                    fPerson = new Person(
                            /*firtNameField.getText(),
                            lastNameField.getText(),
                            emailField.getText(),Double.parseDouble(speedField.getText()),Double.parseDouble(stopspeedField.getText()),""*/);
                    data.add(fPerson);
                } else {
                    int k = -1;
                    if (data.size() > 0) {
                        for (int i = 0; i < data.size(); i++) {
                            if (data.get(i) == fPerson) {
                                k = i;
                            }
                        }
                    }
                    fPerson.setName(firtNameField.getText());
                    data.set(k, fPerson);
                    table.setItems(data);

//  The following will work, but edited person has to be added to the button
//
//                    data.remove(fPerson);
//                    data.add(fPerson);

// add and remove refresh the table, but now move edited person to original spot, 
// it failed again with the following code
//                    while (data.indexOf(fPerson) != k) {
//                        int i = data.indexOf(fPerson);
//                        Collections.swap(data, i, i - 1);
//                    }
                }
                editView.close();
            }
        });
        Button cancelButton = new Button("Cancel");
        cancelButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                editView.close();
            }
        });
        TitledBorder b = new TitledBorder();
        HBox saveCancelButtonBox = new HBox();
        saveCancelButtonBox.getChildren().addAll(saveButton, cancelButton);
        saveCancelButtonBox.setAlignment(Pos.CENTER_RIGHT);
        saveCancelButtonBox.setSpacing(3);

//        saveCancelButtonBox.setBorder( new Border(new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, null, new BorderWidths(3))));
        VBox editBox = new VBox();
        editBox.getChildren().addAll(editPane, saveCancelButtonBox);

        Scene editScene = new Scene(editBox);
        editView.setTitle("Person");
        editView.initStyle(StageStyle.UTILITY);
        editView.initModality(Modality.APPLICATION_MODAL);
        editView.setScene(editScene);
        editView.close();

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.getChildren().addAll(label, table, addEditDeleteButtonBox);
        vbox.setPadding(new Insets(10, 0, 0, 10));

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }
}

And here is my ouput: enter image description here

I am trying to fill different values -> java and dot net in skill 1 and skill 2 column. Kindly help in the same.

Upvotes: 0

Views: 3121

Answers (1)

fabian
fabian

Reputation: 82491

You want to use multiple values. Therefore you cannot store the elements in a single String field (at least not in a convenient way). You need to use a data type that supports multiple values, such as List<String>. PropertyValueFactory cannot handle this type however, so you need to use a custom cellValueFactory:

public static class Person {
    ...
    private final List<String> skills = new ArrayList<>();

    public List<String> getSkills() {
        return skills;
    }

    ...
}

Column creation

for (int i = 0; i < nestedColumnsNameList.size(); i++) {
    final int index = i;
    TableColumn<Person, String> ageValCol = new TableColumn<>(nestedColumnsNameList.get(i));

    // get data from list using index
    ageValCol.setCellValueFactory(cellData -> Bindings.createObjectBinding(() -> cellData.getValue().getSkills().get(index)));

    skillSetCol.getColumns().add(ageValCol);
}

Item creation

for (int i = 0; i < nameList.size(); i++) {
    Person p = new Person();
    p.setName(nameList.get(i));

    p.getSkills().addAll(skillList);

    data.add(p);
}

Upvotes: 1

Related Questions