I have searched at Google and Stackoverflow for this and I just don't get the given examples. Can someone please explain it to me.
I want to add a button to the last column of a table view and when it gets clicked it should trigger a listener and pass the object of the buttons row. I just do not get the following example from gist.github.com:
This is my full current code:
public class SchermdeelWerkplaats extends BorderPane{ //ATD moeder klasse met alle collecties etc. private ATD $; TableView tabel = new TableView(); Button nieuwTaak = new Button("Nieuwe taak inboeken"); final ObservableList<Task> data = FXCollections.observableArrayList(); public SchermdeelWerkplaats(ATD a) { $ = a; data.addAll($.agenda); tabel.setEditable(false); tabel.setPlaceholder(new Label("Geen taken")); TableColumn c1 = new TableColumn("datum"); c1.setMinWidth(200); TableColumn c2 = new TableColumn("type"); c2.setMinWidth(100); TableColumn c3 = new TableColumn("uren"); c3.setMinWidth(100); TableColumn c4 = new TableColumn("klaar"); c4.setMinWidth(200); TableColumn c5 = new TableColumn("Werknemer"); c5.setMinWidth(100); TableColumn c6= new TableColumn("Auto"); c6.setMinWidth(400); TableColumn c7= new TableColumn("Actie"); c7.setMinWidth(400); TableColumn col_action = new TableColumn<>("Action"); col_action.setCellValueFactory( new Callback<TableColumn.CellDataFeatures<Task, Boolean>, ObservableValue<Boolean>>() { @Override public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Task, Boolean> p) { return new SimpleBooleanProperty(p.getValue() != null); } }); col_action.setCellFactory( new Callback<TableColumn<Task, Task>, TableCell<Task, Task>>() { @Override public TableCell<Task, Task> call(TableColumn<Task, Task> p) { return new ButtonCell(); } } ); c1.setCellValueFactory( new PropertyValueFactory<Task,Date>("date") ); c2.setCellValueFactory( new PropertyValueFactory<Task,Task.TaskType>("type") ); c3.setCellValueFactory( new PropertyValueFactory<Task,Double>("hours") ); c4.setCellValueFactory( new PropertyValueFactory<Task,Boolean>("done") ); c5.setCellValueFactory( new PropertyValueFactory<Task,Employee>("employee") ); c6.setCellValueFactory( new PropertyValueFactory<Task,Car>("car") ); tabel.getColumns().addAll(c1, c2, c3, c4, c5, c6, c7); tabel.setItems(data); setCenter(tabel); setBottom(nieuwTaak); } //letterlijk van internet geplukt en datatype aangepast private class ButtonCell extends TableCell<Task, Task> { private Button cellButton; ButtonCell(){ cellButton = new Button("jjhjhjh"); cellButton.setOnAction(new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent t) { // do something when button clicked Task record = getItem(); // do something with record.... } }); } //Display button if the row is not empty @Override protected void updateItem(Task record, boolean empty) { super.updateItem(record, empty); if(!empty){ cellButton.setText("Something with "+record); setGraphic(cellButton); } else { setGraphic(null); } } } }
Now the part where I have to create a ButtonCell extends TableCell
is understandable. But how to assign this to the column?
I understand this:
c1.setCellValueFactory( new PropertyValueFactory<Task,Date>("date") );
But not this:
TableColumn col_action = new TableColumn<>("Action"); col_action.setCellValueFactory( new Callback<TableColumn.CellDataFeatures<Task, Boolean>, ObservableValue<Boolean>>() { @Override public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Task, Boolean> p) { return new SimpleBooleanProperty(p.getValue() != null); } }); col_action.setCellFactory( new Callback<TableColumn<Task, Task>, TableCell<Task, Task>>() { @Override public TableCell<Task, Task> call(TableColumn<Task, Task> p) { return new ButtonCell(); } } );
You can create a Button by instantiating the javafx. scene. control. Button class of this package and, you can set text to the button using the setText() method.
The TableView class provides built-in capabilities to sort data in columns. Users can alter the order of data by clicking column headers. The first click enables the ascending sorting order, the second click enables descending sorting order, and the third click disables sorting. By default, no sorting is applied.
To be able to render the column, TableColumn
needs cellValueFactory. But the "action" column does not exist in underlying data model. In this case, I just give some dummy value to cellValueFactory and move on:
public class JustDoIt extends Application { private final TableView<Person> table = new TableView<>(); private final ObservableList<Person> data = FXCollections.observableArrayList( new Person("Jacob", "Smith"), new Person("Isabella", "Johnson"), new Person("Ethan", "Williams"), new Person("Emma", "Jones"), new Person("Michael", "Brown") ); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage.setWidth(450); stage.setHeight(500); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName")); TableColumn actionCol = new TableColumn("Action"); actionCol.setCellValueFactory(new PropertyValueFactory<>("DUMMY")); Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory = // new Callback<TableColumn<Person, String>, TableCell<Person, String>>() { @Override public TableCell call(final TableColumn<Person, String> param) { final TableCell<Person, String> cell = new TableCell<Person, String>() { final Button btn = new Button("Just Do It"); @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setGraphic(null); setText(null); } else { btn.setOnAction(event -> { Person person = getTableView().getItems().get(getIndex()); System.out.println(person.getFirstName() + " " + person.getLastName()); }); setGraphic(btn); setText(null); } } }; return cell; } }; actionCol.setCellFactory(cellFactory); table.setItems(data); table.getColumns().addAll(firstNameCol, lastNameCol, actionCol); Scene scene = new Scene(new Group()); ((Group) scene.getRoot()).getChildren().addAll(table); stage.setScene(scene); stage.show(); } public static class Person { private final SimpleStringProperty firstName; private final SimpleStringProperty lastName; private Person(String fName, String lName) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } } }
Here is my example using awesome Java 8 Functionality and extending TableCell class.
Let me give a quick explanation of what I am doing: I created a ActionButtonTableCell class that extends TableCell. And then you can use java 8 lamda functions to create an Action for the button.
import java.util.function.Function; import javafx.event.ActionEvent; import javafx.scene.control.Button; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.util.Callback; public class ActionButtonTableCell<S> extends TableCell<S, Button> { private final Button actionButton; public ActionButtonTableCell(String label, Function< S, S> function) { this.getStyleClass().add("action-button-table-cell"); this.actionButton = new Button(label); this.actionButton.setOnAction((ActionEvent e) -> { function.apply(getCurrentItem()); }); this.actionButton.setMaxWidth(Double.MAX_VALUE); } public S getCurrentItem() { return (S) getTableView().getItems().get(getIndex()); } public static <S> Callback<TableColumn<S, Button>, TableCell<S, Button>> forTableColumn(String label, Function< S, S> function) { return param -> new ActionButtonTableCell<>(label, function); } @Override public void updateItem(Button item, boolean empty) { super.updateItem(item, empty); if (empty) { setGraphic(null); } else { setGraphic(actionButton); } } }
The implementation is then as simple as this, This is a sample button to remove the item from the table:
column.setCellFactory(ActionButtonTableCell.<Person>forTableColumn("Remove", (Person p) -> { table.getItems().remove(p); return p; }));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With