JavaFX自定义DataFormat的拖放功能

5

概述

我正在为Java FX应用程序设置拖放功能。当我尝试从Dragboard中获取自定义数据时,我得到的是一个java.nio.HeapByteBuffer而不是JavaDoc所建议的Object。这个字节缓冲区不能强制转换成我的原始数据类型。

我在Scala中工作,因此语法略有不同,但你可以理解大意。也许正是因为我在Scala中,所以我得到了这个HeapByteBuffer而不是普通的Object

详细说明

好的,现在我要创建一个可拖放的JavaFX控件。我将附加一个String和一个MyObjectString可以被检索,但MyObject不能。
请注意,我知道有更简单的方法可以附加简单的字符串到拖放板上,但这只是一个示例,以展示也可以从拖放板中检索MyObject

在这里,我创建了一个可拖动的自定义组件。 当它被拖动时,会在拖放板上附加两个对象:一个MyObject和一个String

class ToolboxItem
    extends Label {

    setOnDragDetected(new EventHandler[MouseEvent] {
        def handle(event: MouseEvent) {
        val dragboard = startDragAndDrop(TransferMode.COPY)
        val content = new ClipboardContent()
        content.put(DnDTarget.DndString, "sean is cool")
        content.put(DnDTarget.DndObject, new MyObject)
        dragboard.setContent(content)
        event.consume()
    }

}

MyObject非常简单,只是为了让我们开始使用它:

class MyObject
    extends Serilaizable

现在,当我接收到拖放事件时,我想从这个事件中获取数据。
(同时,在这里定义我的DataFormat)
object DnDTarget {

    val DndString = new DataFormat("my.custom.dnd.string")
    val DndObject = new DataFormat("my.custom.dnd.object")

}

trait DnDTarget
    extends Node {

    setOnDragOver(new EventHandler[DragEvent]() {
        def handle(event: DragEvent) {
            if (valid(event)) {
                val dragboard = event.getDragboard
                val myString = dragboard.getContent(DnDTarget.DndString)
                val myObject = dragboard.getContent(DnDTarget.DndObject)
                myString.asInstanceOf[String]   // no problem
                myObject.asInstanceOf[MyObject] // throws exception
                event.acceptTransferModes(TransferMode.COPY)
            }
            event.consume()
        }
    })
}

好的,那么调用myString.asInstanceOf[String]是很好的,我得到了我的String。然而,myObject.asInstanceOf[MyObject]会抛出一个ClassCastException,提示:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.nio.HeapByteBuffer cannot be cast to com.example.MyObject

注意:我这里没有使用ScalaFX,仅仅在Scala中使用了原生JavaFX。

1个回答

3
我曾经遇到过类似的问题,当我尝试在JavaFX 8中实现拖放时。在实现自定义类型时,在反序列化期间遇到了相同的异常。最终,我找出了我的问题所在。
这是我的一个错误,我的"MyObject"类实际上是不可反序列化的(在我的情况下,MyObject扩展了一个没有实现Serializable并且没有默认无参构造函数的超类型,在这种情况下必须要有)。无论如何,在测试"MyObject"可以在单元测试中进行序列化/反序列化之后,我的JavaFX拖放开始工作了。据我所知,问题在于: JavaFX错误处理似乎隐藏了在反序列化期间的任何异常,并返回序列化的字节缓冲区而不是您反序列化的对象。 这是否是良好的错误处理方式存在争议。
在您的情况下,您可以使用以下Java代码尝试自己反序列化从JavaFX获取的字节缓冲区来进行测试:
public static MyObject deserialize(ByteBuffer buffer) {
    try {
        ByteArrayInputStream is = new ByteArrayInputStream(buffer.array());
        ObjectInputStream ois = new ObjectInputStream(is);
        MyObject obj = (MyObject) ois.readObject();
        return obj;
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

如果这个方法抛出异常,说明你有一个错误。修复它,然后拖放功能应该会再次正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接