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);
}
}