Dragging and dropping list view items between different javafx windows

删除回忆录丶 提交于 2019-12-01 09:04:06

It does look like the gesture source and target both get set to null when the drag leaves the JavaFX application (e.g. moving it between two windows).

For the gesture source, you may need to manage that yourself by creating a property and setting its value in the onDragDetected handler.

The gesture target is surely just the tile pane to which you attached the onDragDropped listener. So I don't see that you need to access that from the event; though you could use the same technique.

Example:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class DnDListViews extends Application {

    private int counter = 0 ;

    private final ObjectProperty<ListCell<String>> dragSource = new SimpleObjectProperty<>();

    @Override
    public void start(Stage primaryStage) {
        populateStage(primaryStage);
        primaryStage.show();

        Stage anotherStage = new Stage();
        populateStage(anotherStage);
        anotherStage.setX(primaryStage.getX() + 300);
        anotherStage.show();
    }

    private void populateStage(Stage stage) {
        ListView<String> listView = new ListView<>();
        for (int i=0; i<5; i++ ) {
            listView.getItems().add("Item "+(++counter));
        }

        listView.setCellFactory(lv -> {
           ListCell<String> cell = new ListCell<String>(){
               @Override
               public void updateItem(String item , boolean empty) {
                   super.updateItem(item, empty);
                   setText(item);
               }
           };

           cell.setOnDragDetected(event -> {
               if (! cell.isEmpty()) {
                   Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);
                   ClipboardContent cc = new ClipboardContent();
                   cc.putString(cell.getItem());
                   db.setContent(cc);
                   dragSource.set(cell);
               }
           });

           cell.setOnDragOver(event -> {
               Dragboard db = event.getDragboard();
               if (db.hasString()) {
                   event.acceptTransferModes(TransferMode.MOVE);
               }
           });

           cell.setOnDragDone(event -> listView.getItems().remove(cell.getItem()));

           cell.setOnDragDropped(event -> {
               Dragboard db = event.getDragboard();
               if (db.hasString() && dragSource.get() != null) {
                   // in this example you could just do
                   // listView.getItems().add(db.getString());
                   // but more generally:

                   ListCell<String> dragSourceCell = dragSource.get();
                   listView.getItems().add(dragSourceCell.getItem());
                   event.setDropCompleted(true);
                   dragSource.set(null);
               } else {
                   event.setDropCompleted(false);
               }
           });

           return cell ;
        });

        BorderPane root = new BorderPane(listView);
        Scene scene = new Scene(root, 250, 450);
        stage.setScene(scene);

    }

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

If the dragboard supported attaching arbitrary object references for drag and drop within the same JVM (see JIRA request, and vote if so inclined) then this would be quite a bit easier...

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!