2015-08-29 52 views
5

Pracuję nad TableView (FXML), w którym chcę mieć wszystkie wiersze z dołączonym przyciskiem usuwania w ostatniej kolumnie.FXML, JavaFX 8, TableView: Utwórz przycisk usuwania w każdym wierszu i usuń odpowiednio wiersz

Oto film, który pokazuje, co to znaczy: YouTube Delete Button in TableView

Oto co mam w głównej klasie kontrolera:

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

    }); 
} 

każdym razem uruchomić aplikację, postaram kliknąć przycisk Usuń z losowych wierszy, ale zawsze usuwa pierwszy wiersz. Chyba metoda addListener, której używam do listy, nie jest poprawnie zaimplementowana, a indexOf (newValue) zawsze wynosi 0 przy każdej inicjalizacji.

Jednak będzie działać, jeśli najpierw kliknę wiersz, a następnie kliknę przycisk usuwania. Ale tego nie chcę. Chcę, aby użytkownicy mogli usunąć dowolny wiersz, jeśli naciśniemy przycisk usuwania bez wybierania wiersza.

Doceń pomoc dla facetów!

+0

podaj SSCCE który demonstruje problem – kleopatra

Odpowiedz

10

Potrzebna jest niestandardowa fabryka komórek zdefiniowana dla kolumny zawierającej przycisk kasowania.

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

Oto przykładowa aplikacja. Nie używa FXML, ale można go łatwo dostosować do pracy z FXML. Wystarczy kliknąć przycisk "Unfriend" w kolumnie "Anti-social", aby usunąć znajomego. Zrób to dużo, a wkrótce zabraknie Ci przyjaciół.

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

Dziękuję bardzo! Zdecydowanie dobrze współpracuje również z FXML. Wystarczy podać informacje innym osobom mającym ten sam problem: wstawiłem nową wartość TableColumn i usunęłem metodę del() (początkowo utworzyłem klasę Person, która akceptuje również przycisk w swoim konstruktorze i stąd pochodzą błędy). –