【问题标题】:JavaFX DragAndDrop with custom DataFormat带有自定义 DataFormat 的 JavaFX DragAndDrop
【发布时间】:2013-05-24 16:17:46
【问题描述】:

概述

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

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

细节

好的,这里我将创建可以拖放的JavaFX 控件。我要附上StringMyObjectString 可以被检索,而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 说:

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

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

【问题讨论】:

    标签: java scala drag-and-drop javafx bytebuffer


    【解决方案1】:

    我在尝试在 JavaFX 8 中实现拖放时遇到了类似的问题。在实现自定义类型时,我在反序列化期间遇到了同样的异常。我最终弄清楚了我的问题所在。

    这是我的一个错误,我的“MyObject”类实际上不是可反序列化的(在我的情况下,MyObject 扩展了一个未实现可序列化并且没有默认无参数构造函数的超类型,它在这种情况下必须有)。无论如何,在单元测试中测试“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);
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 2014-08-30
      • 2021-08-12
      • 2016-04-22
      • 2013-11-10
      • 2014-12-29
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      • 2017-05-04
      相关资源
      最近更新 更多