Putting button into the table column more elegantly


Question

Here is a SSCCE demonstrating how to put a Button into the TableView column. It works but with little unpleasant behavior. When the table rows are scrolled down by mouse using the scroll bar, 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?

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<Person> personTable = new TableView<>();
    private TableColumn<Person, String> nameCol = new TableColumn<>("name");
    private TableColumn<Person, Double> salaryCol = new TableColumn<>("salary");
    private TableColumn<Person, String> actionCol = new TableColumn<>("action");

    @Override
    public void start(Stage primaryStage) {
        ObservableList<Person> data = FXCollections.observableArrayList();
        for (int i = 0; i < 40; i++) {
            data.add(new Person("person_" + i, i * 100d));
        }

        nameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
        salaryCol.setCellValueFactory(new PropertyValueFactory<Person, Double>("salary"));
        actionCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name")); // "name" here is for just to render the column

        Callback<TableColumn<Person, String>, TableCell<Person, String>> printColumnCellFactory = //
                new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {

            @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<ActionEvent>() {

                                @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);
    }
}
1
4
4/9/2012 8:24:06 AM

Accepted Answer

Upgrading to version 2.1 resolved the problem.

0
7/5/2012 4:33:17 PM

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