title: Putting button into the table column more elegantly
body: <p>Here is a SSCCE demonstrating how to put a <code>Button</code> into the <code>TableView</code> column. It works but with little unpleasant behavior. When the table rows are scrolled down <b>by mouse using the scroll bar</b>, the new rendered buttons are not shown immediately. They are shown only when the mouse is released and then moved. I think there is another more elegant way of displaying the button in the table column and when clicked doing some stuff related to the selected row. Any suggestions?</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.event.ActionEvent;
  import javafx.event.EventHandler;
  import javafx.scene.Scene;
  import javafx.scene.control.*;
  import javafx.scene.control.cell.PropertyValueFactory;
  import javafx.scene.layout.StackPane;
  import javafx.scene.layout.StackPaneBuilder;
  import javafx.stage.Stage;
  import javafx.util.Callback;
  
  public class ButtonDemo extends Application {
  
      private TableView&lt;Person&gt; personTable = new TableView&lt;&gt;();
      private TableColumn&lt;Person, String&gt; nameCol = new TableColumn&lt;&gt;("name");
      private TableColumn&lt;Person, Double&gt; salaryCol = new TableColumn&lt;&gt;("salary");
      private TableColumn&lt;Person, String&gt; actionCol = new TableColumn&lt;&gt;("action");
  
      @Override
      public void start(Stage primaryStage) {
          ObservableList&lt;Person&gt; data = FXCollections.observableArrayList();
          for (int i = 0; i &lt; 40; i++) {
              data.add(new Person("person_" + i, i * 100d));
          }
  
          nameCol.setCellValueFactory(new PropertyValueFactory&lt;Person, String&gt;("name"));
          salaryCol.setCellValueFactory(new PropertyValueFactory&lt;Person, Double&gt;("salary"));
          actionCol.setCellValueFactory(new PropertyValueFactory&lt;Person, String&gt;("name")); // "name" here is for just to render the column
  
          Callback&lt;TableColumn&lt;Person, String&gt;, TableCell&lt;Person, String&gt;&gt; printColumnCellFactory = //
                  new Callback&lt;TableColumn&lt;Person, String&gt;, TableCell&lt;Person, String&gt;&gt;() {
  
              @Override
              public TableCell call(final TableColumn param) {
                  final TableCell cell = new TableCell() {
  
                      @Override
                      public void updateItem(Object item, boolean empty) {
                          super.updateItem(item, empty);
                          if (empty) {
                              setText(null);
                              setGraphic(null);
                          } else {
                              final Button btnPrint = new Button("print name");
                              btnPrint.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
  
                                  @Override
                                  public void handle(ActionEvent event) {
                                      param.getTableView().getSelectionModel().select(getIndex());
                                      Person item = personTable.getSelectionModel().getSelectedItem();
                                      if (item != null) {
                                          System.out.println(item.getName());
                                      }
                                  }
                              });
                              setGraphic(btnPrint);
                              setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                          }
                      }
                  };
                  return cell;
              }
          };
          actionCol.setCellFactory(printColumnCellFactory);
  
          personTable.setItems(data);
          personTable.getColumns().addAll(nameCol, salaryCol, actionCol);
          StackPane root = StackPaneBuilder.create().children(personTable).build();
          primaryStage.setScene(new Scene(root, 300, 250));
          primaryStage.show();
      }
  
      public class Person {
  
          private String name;
          private Double salary;
  
          public Person(String name, Double salary) {
              this.name = name;
              this.salary = salary;
          }
  
          public String getName() {
              return name;
          }
  
          public Double getSalary() {
              return salary;
          }
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>