FXML, JavaFX 8, TableView: Make a delete button in each row and delete the row accordingly

I am working on a TableView (FXML) where I want all rows to be followed by a delete button in the last column.

Here is a video that shows what I mean: YouTube Delete button in TableView

Here is what I have in my main controller class:

public Button del() { Button del = new Button(); del.setText("X"); del.setPrefWidth(30); del.setOnAction(new EventHandler<ActionEvent>() { public void handle(ActionEvent event) { int i = index.get(); if(i > -1) { goals.remove(i); list.getSelectionModel().clearSelection(); } } }); return del; } private SimpleIntegerProperty index = new SimpleIntegerProperty(); @Override public void initialize(URL location, ResourceBundle resources){ //DateFormat df = new SimpleDateFormat("dd MMM yyyy"); sdate.setValue(LocalDate.now()); edate.setValue(LocalDate.now()); seq.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("id")); gol.setCellValueFactory(new PropertyValueFactory<Goals, String>("goal")); sdt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("sdte")); edt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("edte")); prog.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("pb")); del.setCellValueFactory(new PropertyValueFactory<Goals, Button>("x")); list.setItems(goals); list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() { @Override public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) { index.set(goals.indexOf(newValue)); System.out.println("Index is: "+goals.indexOf(newValue)); } }); } 

Every time I launch the application, I try to press the delete button from random lines, but always deletes the first line. I assume that the addListener method that I use for the list does not execute properly, and indexOf (newValue) is always 0 on every initialization.

However, it will work if I click on the line first and then click on the "Delete" button. But that I do not want. I want users to be able to delete any row if they click the delete button without selecting a row.

Appreciate your help to the guys!

+5
source share
1 answer

For a column containing a delete button, you need a special factory cell.

 TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social"); unfriendCol.setCellValueFactory( param -> new ReadOnlyObjectWrapper<>(param.getValue()) ); unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() { private final Button deleteButton = new Button("Unfriend"); @Override protected void updateItem(Person person, boolean empty) { super.updateItem(person, empty); if (person == null) { setGraphic(null); return; } setGraphic(deleteButton); deleteButton.setOnAction( event -> getTableView().getItems().remove(person) ); } }); 

Here is an example application. It does not use FXML, but you can easily adapt it to work with FXML. Just click the "Friends" button in the "Antisocial" column to remove a friend. Do it a lot and you will end up with friends soon.

antisocial

 import javafx.application.Application; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.stage.Stage; public class GestureEvents extends Application { private 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) { final Label label = new Label("Friends"); label.setFont(new Font("Arial", 20)); final Label actionTaken = new Label(); TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social"); unfriendCol.setMinWidth(40); unfriendCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue())); unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() { private final Button deleteButton = new Button("Unfriend"); @Override protected void updateItem(Person person, boolean empty) { super.updateItem(person, empty); if (person == null) { setGraphic(null); return; } setGraphic(deleteButton); deleteButton.setOnAction(event -> data.remove(person)); } }); TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory( new PropertyValueFactory<>("firstName")); TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory( new PropertyValueFactory<>("lastName")); table.setItems(data); table.getColumns().addAll(unfriendCol, firstNameCol, lastNameCol); table.setPrefHeight(250); final VBox vbox = new VBox(); vbox.setSpacing(5); vbox.setPadding(new Insets(10, 10, 10, 10)); vbox.getChildren().addAll(label, table, actionTaken); VBox.setVgrow(table, Priority.ALWAYS); stage.setScene(new Scene(vbox)); 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); } } } 
+10
source

All Articles