Adding new row with button to javafx tableview


I have defined a tableview in fxml. It is something like the following:

SNO Name DOB Action

The Action column would contain buttons in each row with text "delete". I have two questions:

  1. How do I add this delete button to each new row last cell in javafx?
  2. How do I get the index of the row whose delete button is clicked?(So that I can delete the row or do other event handling work)
12/15/2013 4:41:02 PM

Accepted Answer

I think this example use for your project just go through it and implement in your project.` package checkboxdemo;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

 * @author reegan
public class Checkboxdemo extends Application {

    static int i = 0;

    public void start(Stage primaryStage) {
        CheckBox checkBox = new CheckBox();
        checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            public void changed(ObservableValue ov,
                    Boolean old_val, Boolean new_val) {
                if (ov.getValue() == true) {
                    i = i + 1;



        TableView tableView = new TableView();
        TableColumn column = new TableColumn("check");
        TableColumn column1 = new TableColumn("Name");


        VBox root = new VBox();

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");


     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     * @param args the command line arguments
   // public static void main(String[] args) {
     //   launch(args);
   // }

package checkboxdemo;
public class Person {
  private StringProperty firstName;
  private StringProperty lastName;

  public Person(String firstName, String lastName) {

  public final void setFirstName(String value) { firstNameProperty().set(value); }
  public final void setLastName(String value) { lastNameProperty().set(value); }
  public String getFirstName() { return firstNameProperty().get(); }
  public String getLastName() { return lastNameProperty().get(); }

  public StringProperty firstNameProperty() {
    if (firstName == null) firstName = new SimpleStringProperty(this, "firstName");
    return firstName;
  public StringProperty lastNameProperty() {
    if (lastName == null) lastName = new SimpleStringProperty(this, "lastName");
    return lastName;

and in TableView add the button in cell

package checkboxdemo;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.Callback;

public class TableViewWithAddButtonExample extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(final Stage stage) {
//    stage.getIcons().add(new Image(""));  // icon license: Linkware (Backlink to required)

    // create a table.
    final TableView<Person> table = new TableView<>(
        new Person("Jacob", "Smith"),
        new Person("Isabella", "Johnson"),
        new Person("Ethan", "Williams"),
        new Person("Emma", "Jones"),
        new Person("Michael", "Brown")

    // define the table columns.
    TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
    firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
    TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
    lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
    TableColumn<Person, Boolean> actionCol = new TableColumn<>("Action");

    // define a simple boolean cell value for the action column so that the column will only be shown for non-empty rows.
    actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, Boolean>, ObservableValue<Boolean>>() {
      @Override public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Person, Boolean> features) {
        return new SimpleBooleanProperty(features.getValue() != null);

    // create a cell value factory with an add button for each row in the table.
    actionCol.setCellFactory(new Callback<TableColumn<Person, Boolean>, TableCell<Person, Boolean>>() {
      @Override public TableCell<Person, Boolean> call(TableColumn<Person, Boolean> personBooleanTableColumn) {
        return new AddPersonCell(stage, table);

    table.getColumns().setAll(firstNameCol, lastNameCol, actionCol);

    stage.setScene(new Scene(table));;

  /** A table cell containing a button for adding a new person. */
  private class AddPersonCell extends TableCell<Person, Boolean> {
    // a button for adding a new person.
    final Button addButton       = new Button("Add");
    // pads and centers the add button in the cell.
    final StackPane paddedButton = new StackPane();
    // records the y pos of the last button press so that the add person dialog can be shown next to the cell.
    final DoubleProperty buttonY = new SimpleDoubleProperty();

     * AddPersonCell constructor
     * @param stage the stage in which the table is placed.
     * @param table the table to which a new person can be added.
    AddPersonCell(final Stage stage, final TableView table) {
      paddedButton.setPadding(new Insets(3));
      addButton.setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
      addButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent actionEvent) {
          showAddPersonDialog(stage, table, buttonY.get());

    /** places an add button in the row only if the row is not empty. */
    @Override protected void updateItem(Boolean item, boolean empty) {
      super.updateItem(item, empty);
      if (!empty) {

   * shows a dialog which displays a UI for adding a person to a table.
   * @param parent a parent stage to which this dialog will be modal and placed next to.
   * @param table the table to which a person is to be added.
   * @param y the y position of the top left corner of the dialog.
  private void showAddPersonDialog(Stage parent, final TableView<Person> table, double y) {
    // initialize the dialog.
    final Stage dialog = new Stage();
    dialog.setTitle("New Person");
    dialog.setX(parent.getX() + parent.getWidth());

    // create a grid for the data entry.
    GridPane grid = new GridPane();
    final TextField firstNameField = new TextField();
    final TextField lastNameField = new TextField();
    grid.addRow(0, new Label("First Name"), firstNameField);
    grid.addRow(1, new Label("Last Name"), lastNameField);
    GridPane.setHgrow(firstNameField, Priority.ALWAYS);
    GridPane.setHgrow(lastNameField, Priority.ALWAYS);

    // create action buttons for the dialog.
    Button ok = new Button("OK");
    Button cancel = new Button("Cancel");

    // only enable the ok button when there has been some text entered.

    // add action handlers for the dialog buttons.
    ok.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent actionEvent) {
        int nextIndex = table.getSelectionModel().getSelectedIndex() + 1;
        table.getItems().add(nextIndex, new Person(firstNameField.getText(), lastNameField.getText()));
    cancel.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent actionEvent) {

    // layout the dialog.
    HBox buttons = HBoxBuilder.create().spacing(10).children(ok, cancel).alignment(Pos.CENTER_RIGHT).build();
    VBox layout = new VBox(10);
    layout.getChildren().addAll(grid, buttons);
    layout.setPadding(new Insets(5));
    dialog.setScene(new Scene(layout));;

12/18/2013 6:47:49 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow