Praveen Vsm
Praveen Vsm

Reputation: 1

Java fx frop drag and drop issue

How to do drag and drop within one listview

I have only one list view (Ed. "player")

My requirement is to move up and down in the same player list

Please find the code i have used

(Not: I am using jdk 1.7 with default javafx)

Example:(player = listView)

listView.setOnDragDetected(new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent event) {

            Dragboard dragBoard = listView.startDragAndDrop(TransferMode.MOVE);

            ClipboardContent content = new ClipboardContent();

            content.putString(listView.getSelectionModel().getSelectedItem().getValue());

            dragBoard.setContent(content);

        }
    });

    listView.setOnDragDone(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent dragEvent) {
            System.out.println("setOnDragDone left");

        }
    });

    listView.setOnDragEntered(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent dragEvent) {
            System.out.println("setOnDragEntered left");

        }
    });

    listView.setOnDragExited(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent dragEvent) {
            System.out.println("setOnDragExited left");

            listView.setBlendMode(null);
        }
    });

    listView.setOnDragOver(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent dragEvent) {
            System.out.println("setOnDragOver left");

            dragEvent.acceptTransferModes(TransferMode.MOVE);
        }
    });

    listView.setOnDragDropped(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent dragEvent) {

                String context = dragEvent.getDragboard().getString();


                dragEvent.setDropCompleted(true);
            }

        }
    });

I am new to javafx

Would you please help on this regard

Upvotes: 0

Views: 3380

Answers (1)

James_D
James_D

Reputation: 209225

Don't register the drag handlers on the ListView: you will have no way of knowing which cells the drag started and ended on. Instead, you need to register the handlers on the cells. The details get a little tricky, but the basic idea is to create a cell factory in which you create the custom cells; here you can set up the drag and drop handlers.

Here's an example:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class DragAndDropListView extends Application {

    @Override
    public void start(Stage primaryStage) {
        final ListView<String> listView = new ListView<>();
        for (int i=1; i<=20; i++) {
            listView.getItems().add("Item "+i);
        }

        final IntegerProperty dragFromIndex = new SimpleIntegerProperty(-1);

        listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {

            @Override
            public ListCell<String> call(ListView<String> lv) {
                final ListCell<String> cell = new ListCell<String>() {
                    @Override
                    public void updateItem(String item, boolean empty) {
                        super.updateItem(item,  empty);
                        if (empty) {
                            setText(null);
                        } else {
                            setText(item);
                        }
                    }
                };

                cell.setOnDragDetected(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent event) {
                        if (! cell.isEmpty()) {
                            dragFromIndex.set(cell.getIndex());
                            Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);
                            ClipboardContent cc = new ClipboardContent();
                            cc.putString(cell.getItem());
                            db.setContent(cc);
                            // Java 8 only:
//                          db.setDragView(cell.snapshot(null, null));
                        }
                    }
                });

                cell.setOnDragOver(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        if (dragFromIndex.get() >= 0 && dragFromIndex.get() != cell.getIndex()) {
                            event.acceptTransferModes(TransferMode.MOVE);
                        }
                    }
                });


                // highlight drop target by changing background color:
                cell.setOnDragEntered(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        if (dragFromIndex.get() >= 0 && dragFromIndex.get() != cell.getIndex()) {
                            // should really set a style class and use an external style sheet,
                            // but this works for demo purposes:
                            cell.setStyle("-fx-background-color: gold;");
                        }
                    }
                });

                // remove highlight:
                cell.setOnDragExited(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        cell.setStyle("");
                    }
                });

                cell.setOnDragDropped(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {

                        int dragItemsStartIndex ;
                        int dragItemsEndIndex ;
                        int direction ;
                        if (cell.isEmpty()) {
                            dragItemsStartIndex = dragFromIndex.get();
                            dragItemsEndIndex = listView.getItems().size();
                            direction = -1;
                        } else {
                            if (cell.getIndex() < dragFromIndex.get()) {
                                dragItemsStartIndex = cell.getIndex();
                                dragItemsEndIndex = dragFromIndex.get() + 1 ;
                                direction = 1 ;
                            } else {
                                dragItemsStartIndex = dragFromIndex.get();
                                dragItemsEndIndex = cell.getIndex() + 1 ;
                                direction = -1 ;
                            }
                        }

                        List<String> rotatingItems = listView.getItems().subList(dragItemsStartIndex, dragItemsEndIndex);
                        List<String> rotatingItemsCopy = new ArrayList<>(rotatingItems);
                        Collections.rotate(rotatingItemsCopy, direction);
                        rotatingItems.clear();
                        rotatingItems.addAll(rotatingItemsCopy);
                        dragFromIndex.set(-1);
                    }
                });

                cell.setOnDragDone(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        dragFromIndex.set(-1);
                        listView.getSelectionModel().select(event.getDragboard().getString());
                    }
                });


                return cell ;
            }


        });

        BorderPane root = new BorderPane();
        root.setCenter(listView);
        Scene scene = new Scene(root, 250, 400);
        scene.getStylesheets().add(getClass().getResource("drag-and-drop-list.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

This will enable you to drag any element and drop it onto any other. For example dragging the third item in the list

enter image description here

and dropping it on the first item results in this:

enter image description here

In Java 8 you can also add the line

db.setDragView(cell.snapshot(null, null));

to the setOnDragDetected(...) method to get a better visual on the drag.

Upvotes: 3

Related Questions