5

概述

我正在 Java FX 应用程序中设置拖放。当我尝试从JavaDoc stuggest中获取自定义数据时,Dragboard我得到的是 ajava.nio.HeapByteBuffer而不是a。Object此字节缓冲区无法转换为我的原始数据类型。

我在 Scala 工作,所以语法有点不同,但你明白了。但是,也许是因为我在 Scala 中,所以我得到了这个HeapByteBuffer而不是常规的Object

细节

好的,这里我要创建可以拖放的JavaFX控件。我要附上 aString和 a MyObject; String可以检索,而不能检索MyObject
请注意,我知道有更简单的方法可以将简单的字符串附加到拖动板上,这只是一个示例,表明它也MyObject应该可以从拖动板上检索。

在这里,我创建了一个可以拖动的自定义组件。拖动时,拖动板上会附加两个对象: aMyObject和 a 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

现在,当我收到拖动事件时,我想从事件中获取这些数据。
(另外,在这里我定义了 my 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说法:

线程“JavaFX 应用程序线程”中的异常 java.lang.ClassCastException:java.nio.HeapByteBuffer 无法转换为 com.example.MyObject

注意:我在这里没有使用 ScalaFX,Scala 中的 vanilla JavaFX

4

1 回答 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);
    }
}

如果此方法引发异常,则说明您有错误。修复它,拖放应该重新开始工作。

于 2015-01-04T12:31:12.917 回答