2015-08-29 27 views
5

Sto lavorando su un TableView (FXML) in cui desidero avere tutte le righe accompagnate da un pulsante di eliminazione nell'ultima colonna.FXML, JavaFX 8, TableView: crea un pulsante di eliminazione in ogni riga ed elimina la riga di conseguenza

Ecco un video che mostra quello che voglio dire: YouTube Delete Button in TableView

Ecco quello che ho nel mio principale classe controller:

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

    }); 
} 

Ogni volta che avvia l'applicazione, cercherò di fare clic sul pulsante Elimina da righe casuali ma elimina sempre la prima riga. Immagino che il metodo addListener che uso per la lista non sia implementato correttamente e indexOf (newValue) sia sempre 0 ad ogni inizializzazione.

Tuttavia, funzionerà se faccio prima clic su una riga e poi sul pulsante Elimina. Ma questo non è quello che voglio. Voglio che gli utenti siano in grado di eliminare qualsiasi riga se premono il pulsante Elimina senza selezionare la riga.

Apprezzo il tuo aiuto ragazzi!

+0

si prega di fornire uno SSCCE che illustra il problema – kleopatra

risposta

10

È necessario un factory cella personalizzato definito per la colonna contenente il pulsante Elimina.

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

Ecco un'app campione. Non usa FXML, ma è possibile adattarlo per lavorare con FXML molto facilmente. Basta fare clic su un pulsante "Unfriend" nella colonna "Anti-social" per eliminare un amico. Fatelo molto e sarete presto a corto di amici.

anti-social

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

Grazie mille! Funziona sicuramente anche con FXML. Solo per fornire informazioni agli altri che affrontano lo stesso problema: ho messo una nuova TableColumn e cancellato il metodo del() (inizialmente ho creato una classe Person che accetta anche il pulsante nel suo costruttore e da dove provengono gli errori). –