2 Replies Latest reply: Jun 27, 2013 6:49 AM by 93c1ef64-4cbd-400b-a704-660f386a7d24 RSS

    How to display various content in a TableColumn

    93c1ef64-4cbd-400b-a704-660f386a7d24

      Hello,

       

      I would like to display in one column only the label of an object, and in the second column, based on the property of the object displayed in the first column, display a Text Field or a ChoiceBox.

       

      Is it possible with Cell Factories? If not, what would you recommend to do that and keep the ability to add rows at a specific index with the ObservableList.

        • 1. Re: How to display various content in a TableColumn
          James_D

          Sure it's possible. Just use the same property for both columns and set the custom cell factory on one of them.

           

          Example:

           

           

           

          import java.util.Arrays;
          
          import javafx.application.Application;
          import javafx.beans.property.SimpleStringProperty;
          import javafx.beans.property.StringProperty;
          import javafx.beans.value.ChangeListener;
          import javafx.beans.value.ObservableValue;
          import javafx.collections.FXCollections;
          import javafx.collections.ObservableList;
          import javafx.event.ActionEvent;
          import javafx.event.EventHandler;
          import javafx.scene.Scene;
          import javafx.scene.control.ComboBox;
          import javafx.scene.control.ContentDisplay;
          import javafx.scene.control.TableCell;
          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.BorderPane;
          import javafx.stage.Stage;
          import javafx.util.Callback;
          
          
          public class CustomTableCellExample extends Application {
          
          
            @Override
            public void start(Stage primaryStage) {
            TableView<Employee> table = new TableView<>();
            table.getItems().addAll(
               new Employee("Fred", "Human Resources"),
               new Employee("Jane", "Information Technology"),
               new Employee("Bob", "Management"),
               new Employee("Anne", "Management"),
               new Employee("Bill", "Finance")
            );
            TableColumn<Employee, String> nameCol = new TableColumn<>("Name");
            nameCol.setCellValueFactory(new PropertyValueFactory<Employee, String>("name"));
          
            TableColumn<Employee, String> departmentLabelCol = new TableColumn<>("Department");
            departmentLabelCol.setCellValueFactory(new PropertyValueFactory<Employee, String>("department"));
          
            TableColumn<Employee, String> editDepartmentCol = new TableColumn<>("Edit Department");
            editDepartmentCol.setCellValueFactory(new PropertyValueFactory<Employee, String>("department"));
            editDepartmentCol.setCellFactory(new Callback<TableColumn<Employee,String>, TableCell<Employee,String>>() {
                @Override
                public TableCell<Employee, String> call(TableColumn<Employee, String> param) {
                  return new DepartmentCell();
                }
              });
            editDepartmentCol.setEditable(true);
            table.setEditable(true);
          
            table.getColumns().addAll(Arrays.asList(nameCol, departmentLabelCol, editDepartmentCol));
          
            BorderPane root = new BorderPane();
            root.setCenter(table);
            primaryStage.setScene(new Scene(root, 300, 400));
            primaryStage.show();
            }
          
          
            public static void main(String[] args) {
            launch(args);
            }
          
            static class DepartmentCell extends TableCell<Employee, String> {
             private final ObservableList<String> knownDepartments = FXCollections.observableArrayList("Human Resources", "Information Technology", "Finance");
             private final ComboBox<String> comboBox = new ComboBox<>(knownDepartments);
             private final TextField textField = new TextField();
             DepartmentCell() {
               comboBox.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent event) {
                    commitEdit(comboBox.getSelectionModel().getSelectedItem());
                  }
               });
               textField.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent event) {
                    commitEdit(textField.getText());
                  }
               });
               textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
                  @Override
                  public void changed(ObservableValue<? extends Boolean> obs,
                      Boolean oldValue, Boolean newValue) {
                    if (! newValue) {
                      commitEdit(textField.getText());
                    }
                  }
               });
             }
             @Override
             public void startEdit() {
               super.startEdit();
               if (! isEmpty() ) {
                 setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                 setText(null);
                 if (knownDepartments.contains(getItem())) {
                   comboBox.getSelectionModel().select(getItem());
                   setGraphic(comboBox);
                 } else {
                   textField.setText(getItem());
                   setGraphic(textField);
                 }
               }
             }
             @Override
             public void commitEdit(String item) {
               super.commitEdit(item);
               setContentDisplay(ContentDisplay.TEXT_ONLY);
               setText(item);
               setGraphic(null);
             }
             @Override
             public void cancelEdit() {
               super.cancelEdit();
               setContentDisplay(ContentDisplay.TEXT_ONLY);
               setText(getItem());
               setGraphic(null);
             }
             @Override
             public void updateItem(String item, boolean empty) {
               super.updateItem(item, empty);
               if (empty) {
                 setText(null);
                 setGraphic(null);
               } else {
                 if (isEditing()) {
                   setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                   if (knownDepartments.contains(item)) {
                     comboBox.getSelectionModel().select(item);
                     setGraphic(comboBox);
                   } else {
                     textField.setText(item);
                     setGraphic(textField);
                   }
                 } else {
                   setContentDisplay(ContentDisplay.TEXT_ONLY);
                   setText(item);
                 }
               }
             }
            }
          
            public static class Employee {
             private final StringProperty name ;
             private final StringProperty department ;
             public Employee(String name, String department) {
               this.name = new SimpleStringProperty(this, "name", name);
               this.department = new SimpleStringProperty(this, "department", department);
             }
             public StringProperty nameProperty() {
               return name ;
             }
             public final String getName() {
               return this.name.get();
             }
             public final void setName(String name) {
               this.name.set(name);
             }
             public StringProperty departmentProperty() {
               return department ;
             }
             public final String getDepartment() {
               return this.department.get();
             }
             public final void setDepartment(String department) {
               this.department.set(department);
             }
            }
          }