JavaFX:设置Dragboard内容在Mouse Released事件

时间:2015-06-19 09:30:37

标签: java treeview javafx-8 drag

在我关于处理dragging from a TreeView的问题中,我从James_D得到了很好的答案。这帮助我烹饪了我需要的大部分东西。

我只需要解决一个问题:在丢弃时我需要知道放置位置的确切坐标,因为这实际上决定了需要做什么。 问题是在DRAG_DROPPED事件中,没有可用的drop坐标信息。 Doh,我完全忽略了DragEvent中的getX()getY()。所以这实际上完全解决了我的问题

在我知道之前,我想过使用MOUSE_RELEASED事件的X和Y坐标。但我发现当你在DRAG_DETECTED处理程序(单元格)中设置Dragboard的内容时,这些坐标(以及PickResult都会出错。这对我来说就像一个错误...

我修改了James_D的示例以向您展示我的意思。 当禁用db.setContent(cc);的行时,从TreeView拖动到例如画布上时显示的拾取结果和坐标(我在我的应用程序中拖动的内容)也很好。在启用行的情况下执行完全相同的操作会导致完全错误的PickResult ...这是一个错误,还是我在做一些愚蠢的事情?

以下是示例代码的输出,将元素拖动到画布的左上角:

(禁用线路):PR=PickResult [node = Canvas@4e91835c, point = Point3D [x = 4.0, y = 2.0, z = 0.0], distance = 746.4101615137755

(启用线路):PR=PickResult [node = null, point = Point3D [x = 842.0, y = -500.0, z = 0.0], distance = 746.4101615137755

注意坐标完全是,以及拣选结果突然再也找不到节点......

代码(来自James_D的修改后的样本,以回答我的earlier question

import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.PickResult;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class DragBoard extends Application {

    private static int cellCount = 0;
    private final DataFormat objectDataFormat = new DataFormat("x-application/java-serialized-object");

    @Override
    public void start(Stage primaryStage) {
        TreeView<Integer> tree = new TreeView<>();
        tree.setShowRoot(false);

        Task<TreeItem<Integer>> buildTreeTask = new Task<TreeItem<Integer>>() {

            @Override
            protected TreeItem<Integer> call() throws Exception {
                TreeItem<Integer> treeRoot = new TreeItem<>(0);
                IntStream.range(1, 10).mapToObj(this::createItem)
                        .forEach(treeRoot.getChildren()::add);
                return treeRoot;
            }

            private TreeItem<Integer> createItem(int value) {
                TreeItem<Integer> item = new TreeItem<>(value);
                if (value < 100) {
                    for (int i = 0; i < 10; i++) {
                        item.getChildren().add(createItem(value * 10 + i));
                    }
                }
                return item;
            }

        };

        tree.setCellFactory(tv -> new TreeCell<Integer>() {

            {
                System.out.println("Cells created: " + (++cellCount));

                setOnDragDetected(e -> {
                    if (!isEmpty()) {
                        Dragboard db = startDragAndDrop(TransferMode.COPY);
                        ClipboardContent cc = new ClipboardContent();
                        cc.put(objectDataFormat, getItem());
                        db.setContent(cc);
                        Label label = new Label(String.format("Add %,d", getItem()));
                        new Scene(label);
                        db.setDragView(label.snapshot(null, null));
                    }
                });

                setOnMouseReleased(e -> {
                    Object es = e.getSource();
                    PickResult pr = e.getPickResult();

                    System.out.println("PR=" + pr);
                });
            }

            @Override
            public void updateItem(Integer value, boolean empty) {
                super.updateItem(value, empty);
                if (empty) {
                    setText(null);
                } else {
                    setText(String.format("%,d", value));
                }
            }
        });

        IntegerProperty total = new SimpleIntegerProperty();
        Label label = new Label();
        label.textProperty().bind(total.asString("Total: %,d"));

        label.setOnDragOver(e
                -> e.acceptTransferModes(TransferMode.COPY));

        // in real life use a CSS pseudoclass and external CSS file for the background:
        label.setOnDragEntered(e -> label.setStyle("-fx-background-color: yellow;"));
        label.setOnDragExited(e -> label.setStyle(""));

        label.setOnDragDropped(e -> {
            Dragboard db = e.getDragboard();
            if (db.hasContent(objectDataFormat)) {
                Integer value = (Integer) db.getContent(objectDataFormat);
                total.set(total.get() + value);
                e.setDropCompleted(true);
            }
        });

        BorderPane.setMargin(label, new Insets(10));
        label.setMaxWidth(Double.MAX_VALUE);
        label.setAlignment(Pos.CENTER);

        Canvas canvas = new Canvas(250, 100);
        BorderPane root = new BorderPane(new Label("Loading..."));

        buildTreeTask.setOnSucceeded(e -> {
            tree.setRoot(buildTreeTask.getValue());
            root.setTop(canvas);
            root.setCenter(tree);
            root.setBottom(label);
        });

        primaryStage.setScene(new Scene(root, 250, 400));
        primaryStage.show();

        Thread t = new Thread(buildTreeTask);
        t.setDaemon(true);
        t.start();

    }

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

0 个答案:

没有答案