javafx - 从 JavaFX DragAndDrop 剪贴板访问自定义对象的属性

标签 javafx clipboard

如何使用 getContent() 从 Dragboard 中取出我的实际对象?有没有可能指定类型? Todo 和 Doing 是 Fl​​owPanes - MyRectangle 是自定义组件的示例。

我想要的是: 放一个对象,例如。剪贴板上带有高度、填充颜色等的矩形,并从剪贴板上取回带有高度、颜色等的对象....

private static final DataFormat itemFormat = new DataFormat("custom.item");
MyRectangle myRectangle = generateRectangle();

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

    @Override
    public void handle(MouseEvent event) {
        Dragboard db = myRectangle
            .startDragAndDrop(TransferMode.MOVE);

        ClipboardContent content = new ClipboardContent();
        content.put(taskFormat, myRectangle);

        // Rectangle has height 
        System.out.println(myRectangle.getHeight());
        TaskItem task = new TaskItem();
        task.setTime(6);
        content.put(itemFormat, task);
        db.setContent(content);

        event.consume();
    }
    });

    myRectangle.setOnDragDone(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
        event.consume();
    }
    });

doing.setOnDragOver(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
    if (event.getGestureSource() != doing) {
        event.acceptTransferModes(TransferMode.MOVE);
    }

    event.consume();
    }
});

doing.setOnDragEntered(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
    event.consume();
    }
});

doing.setOnDragExited(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
    event.consume();
    }
});

doing.setOnDragDropped(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
    final Dragboard db = event.getDragboard();
    boolean success = false;
    if (db.hasContent(taskFormat)) {
        MyRectangle rect2 = (MyRectangle) db.getContent(taskFormat);


        System.out.println(rect2.getHeight());
        todo.getChildren().remove(rect2);
        doing.getChildren().add(rect2);
        success = true;
        // doing.getChildren().add(rectangle);
    }
    event.setDropCompleted(success);
    event.consume();
    }
});

private MyRectangle generateRectangle() {
final MyRectangle rect2 = new MyRectangle(0, 0, 10, 10);
rect2.setId("app");
rect2.setArcHeight(8);
rect2.setWidth(80);
rect2.setArcWidth(8);
rect2.setStrokeWidth(1);
rect2.setStroke(Color.WHITE);
rect2.setHeight(60);
return rect2;
}

最佳答案

好吧,您真的应该考虑拥有数据的表示(而不是数据的 View ),即被拖放的对象。您注册一个处理程序来检测节点(数据 View )的拖动,将数据设置到拖板中,然后在成功放置时创建另一个相同数据的 View 。为移动移除前一个节点,不要为复制移除它。

不幸的是,它不起作用。

参见 this 并为此投票 bug/feature ,这将允许您直接执行此操作。

目前,只有实现了 Serializable 的 Java 对象才能放置在拖板上。由于 JavaFX 属性不实现可序列化,因此任何使用这些属性进行数据表示的类(恕我直言,是您想要用来表示要在应用程序中拖放的数据的任何类)。即使您的类是可序列化的,据我所知,该对象在将其放入拖板时被序列化并在您删除它时被反序列化,这意味着您在拖放时会得到一个新对象,而不是对同一对象:这可能不是您想要的。 (如果您通过拖放复制某些内容,然后对其进行编辑,您可能希望两个副本都尊重该编辑。)

因此,就目前而言,我认为解决方案是创建某种本地存储库并将拖动的对象存储在其中。这可能就像 ObjectProperty<?> currentlyDraggedObject 一样简单,或者更复杂的东西,比如 LocalDragboard我在 discussion referenced earlier 的底部实现了. (这只不过是复制你在谷歌上搜索“类型安全异构容器的标准示例”时会找到的代码。)

我不得不说,我发现拖放的方式有点奇怪。 JavaFX 2 及更高版本中的几乎所有内容都是用非常现代的 Java 风格编写的,(几乎)所有内容都非常舒适地使用泛型,一些非常好的并发 API 是为较新的高级并发 API 设计的,所有事件处理都是用关注最近的语言发展,例如 lambda 表达式和流。 Bindings API 甚至似乎对整个响应式(Reactive)编程运动略微倾斜。但是拖放似乎被设计成好像我们唯一想通过拖动手势传输的数据是字符串、图像和文件。就好像 DnD API 的设计者并没有真正理解程序员想要开发他们自己的数据表示类的想法。

因此,在这个外观非常现代的 GUI 框架中,您拥有一个看起来像是 90 年代后期设计的 DnD API(如果是的话)。很奇怪。

关于javafx - 从 JavaFX DragAndDrop 剪贴板访问自定义对象的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22820160/

相关文章:

android - Kotlin Android - 从 fragment 复制到剪贴板

javafx如何在fxml Controller 中使用线程

java - 在 JavaFX 中绘制子像素?

c# - 如何知道 Excel 复制到剪贴板的数据的 .csv 字段分隔符

javascript - 将文本从书签复制到剪贴板

c# - 关闭程序后保留剪贴板信息

javascript - 将剪贴板内容作为字符串变量获取

java - 产生其他服务/任务的后台服务

JavaFX 将正确的数据从一个 Controller 返回到另一个 Controller

css - JavaFx 选项卡 - 外观与 SceneBuilder 不同