Java fx frop拖放问题

时间:2014-09-05 11:05:53

标签: javafx-2

如何在一个列表视图中拖放

我只有一个列表视图(编辑“播放器”)

我的要求是在同一个播放器列表中上下移动

请找到我用过的代码

(不是:我使用jdk 1.7和默认的javafx)

示例:(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);
            }

        }
    });

我是javafx的新手

请你帮忙解决这个问题

1 个答案:

答案 0 :(得分:3)

不要在ListView上注册拖动处理程序:您将无法知道拖动开始和结束的单元格。相反,您需要在单元格上注册处理程序。细节有点棘手,但基本的想法是创建一个单元工厂,在其中创建自定义单元格;在这里你可以设置拖放处理程序。

以下是一个例子:

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

这将使您能够拖动任何元素并将其拖放到任何其他元素上。例如,拖动列表中的第三项

enter image description here

并将其放在第一个项目上会产生以下结果:

enter image description here

在Java 8中,您还可以添加行

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

setOnDragDetected(...)方法以获得更好的视觉效果。