2015-02-19 16 views
5

moim celem jest posortowanie widoku tabeli za pomocą przeciągania i upuszczania. I po to przykład: http://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htmsortuj widok tabeli za pomocą przeciągania i upuszczania (wierszy)

Na przeciągnij i upuść I dodaje fxml poprzez sceny Konstruktor

<TableView fx:id="tableView" onDragDetected="#dragDetected" onDragDropped="#dragDropped" onDragOver="#dragOver" 

i wykonane kontrolerów

@FXML 
    private void dragDetected(MouseEvent event) { 
     System.out.println("dragDetected"); 

     Integer idx; 
     idx = tableView.getSelectionModel().getFocusedIndex(); 
     Dragboard db = tableView.startDragAndDrop(TransferMode.MOVE); 
     ClipboardContent content = new ClipboardContent(); 
     content.putString(idx.toString()); 
     db.setContent(content); 

     System.out.println(idx); 
//  System.out.println(event.getPickResult()); 
     event.consume(); 
    } 

    @FXML 
    private void dragOver(DragEvent event) { 
     event.acceptTransferModes(TransferMode.COPY_OR_MOVE); 
     event.consume(); 
    } 

    @FXML 
    private void dragDropped(DragEvent event) { 
     System.out.println("dragDropped"); 

     System.out.println(event.getTarget()); 
     System.out.println(event.getPickResult()); 
    } 

ale przeciągania spadła nie mogę się wiersz miejsce, w którym upuściłem przedmiot. Wszystko, co dostaję, to informacja o komórce. Text[text="Smith", x=0.0, y=0.0, ...

Jak uzyskać tę pracę? Może Class TableRow<T> może pomóc, ale nie rozumiem, jak go używać.

Odpowiedz

21

Jak można podejrzewać, odpowiedzią jest użycie TableRow. Można to zrobić, ustawiając fabrykę wierszy w tabeli, która służy do tworzenia wierszy tabeli, gdy są one potrzebne. Możesz je utworzyć i ustawić na nich przeciągarki, zanim je zwrócisz.

Tak więc, usuń atrybuty itp. Z FXML, aw metodzie initialize w kontrolerze ustaw przeciągacze w rzędzie.

Oto pełny przykład, używając zwykłego przykładu z samouczków Oracle. W tym przykładzie nie używałem FXML (właśnie stworzyłem widok tabeli bezpośrednio w klasie Java), ale można po prostu przenieść całą konfigurację widoku tabeli do metody initialize.

import java.util.function.Function; 

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.Scene; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableRow; 
import javafx.scene.control.TableView; 
import javafx.scene.input.ClipboardContent; 
import javafx.scene.input.DataFormat; 
import javafx.scene.input.Dragboard; 
import javafx.scene.input.TransferMode; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class TableViewDragRows extends Application { 

    private static final DataFormat SERIALIZED_MIME_TYPE = new DataFormat("application/x-java-serialized-object"); 

    @Override 
    public void start(Stage primaryStage) { 
     TableView<Person> tableView = new TableView<>(); 
     tableView.getColumns().add(createCol("First Name", Person::firstNameProperty, 150)); 
     tableView.getColumns().add(createCol("Last Name", Person::lastNameProperty, 150)); 
     tableView.getColumns().add(createCol("Email", Person::emailProperty, 200)); 

     tableView.getItems().addAll(
      new Person("Jacob", "Smith", "[email protected]"), 
      new Person("Isabella", "Johnson", "[email protected]"), 
      new Person("Ethan", "Williams", "[email protected]"), 
      new Person("Emma", "Jones", "[email protected]"), 
      new Person("Michael", "Brown", "[email protected]") 
     ); 

     tableView.setRowFactory(tv -> { 
      TableRow<Person> row = new TableRow<>(); 

      row.setOnDragDetected(event -> { 
       if (! row.isEmpty()) { 
        Integer index = row.getIndex(); 
        Dragboard db = row.startDragAndDrop(TransferMode.MOVE); 
        db.setDragView(row.snapshot(null, null)); 
        ClipboardContent cc = new ClipboardContent(); 
        cc.put(SERIALIZED_MIME_TYPE, index); 
        db.setContent(cc); 
        event.consume(); 
       } 
      }); 

      row.setOnDragOver(event -> { 
       Dragboard db = event.getDragboard(); 
       if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
        if (row.getIndex() != ((Integer)db.getContent(SERIALIZED_MIME_TYPE)).intValue()) { 
         event.acceptTransferModes(TransferMode.COPY_OR_MOVE); 
         event.consume(); 
        } 
       } 
      }); 

      row.setOnDragDropped(event -> { 
       Dragboard db = event.getDragboard(); 
       if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
        int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE); 
        Person draggedPerson = tableView.getItems().remove(draggedIndex); 

        int dropIndex ; 

        if (row.isEmpty()) { 
         dropIndex = tableView.getItems().size() ; 
        } else { 
         dropIndex = row.getIndex(); 
        } 

        tableView.getItems().add(dropIndex, draggedPerson); 

        event.setDropCompleted(true); 
        tableView.getSelectionModel().select(dropIndex); 
        event.consume(); 
       } 
      }); 

      return row ; 
     }); 


     Scene scene = new Scene(new BorderPane(tableView), 600, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private TableColumn<Person, String> createCol(String title, 
      Function<Person, ObservableValue<String>> mapper, double size) { 

     TableColumn<Person, String> col = new TableColumn<>(title); 
     col.setCellValueFactory(cellData -> mapper.apply(cellData.getValue())); 
     col.setPrefWidth(size); 

     return col ; 
    } 


    public class Person { 
     private final StringProperty firstName = new SimpleStringProperty(this, "firstName"); 
     private final StringProperty lastName = new SimpleStringProperty(this, "lastName"); 
     private final StringProperty email = new SimpleStringProperty(this, "email"); 

     public Person(String firstName, String lastName, String email) { 
      this.firstName.set(firstName); 
      this.lastName.set(lastName); 
      this.email.set(email); 
     } 

     public final StringProperty firstNameProperty() { 
      return this.firstName; 
     } 

     public final String getFirstName() { 
      return this.firstNameProperty().get(); 
     } 

     public final void setFirstName(final String firstName) { 
      this.firstNameProperty().set(firstName); 
     } 

     public final StringProperty lastNameProperty() { 
      return this.lastName; 
     } 

     public final String getLastName() { 
      return this.lastNameProperty().get(); 
     } 

     public final void setLastName(final String lastName) { 
      this.lastNameProperty().set(lastName); 
     } 

     public final StringProperty emailProperty() { 
      return this.email; 
     } 

     public final String getEmail() { 
      return this.emailProperty().get(); 
     } 

     public final void setEmail(final String email) { 
      this.emailProperty().set(email); 
     } 

    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

mógłbyś wyjaśnić bardziej szczegółowe, gdzie umieścić co. (To głupie pytanie prawdopodobnie.) Mój IDE lubi tworzyć klasę 'tv' jeśli wstawię program obsługi po' @FXML private TableView tableView; ' – schasoli

+0

Umieść procedury obsługi w metodzie' initialize() 'kontrolera. –

+1

Witam @ James_D, chciałbym zapytać: dlaczego używamy 'SERIALIZED_MIME_TYPE'? Po co to jest ? – mynameisJEFF

1

pracująca 1 odpowiedź (od James_D) do FMXL:

<TableView fx:id="tableView" GridPane.columnIndex="0" GridPane.rowIndex="1">

public class FXMLTableViewController implements Initializable { 
    private static final DataFormat SERIALIZED_MIME_TYPE = new DataFormat("application/x-java-serialized-object"); 

    @Override 
    public void initialize(URL url, ResourceBundle resourceBundle) { 
     tableView.setRowFactory(tv -> { 
     ... 
      return row ; 
     }); 
    } 

    @FXML 
    private TableView<Person> tableView; 
    ... 
+0

Właśnie wróciłem, aby edytować odpowiedź, aby pokazać wersję opartą na FXML, ale tak, to jest dokładnie poprawne. –

Powiązane problemy