5

概要

Java FX アプリケーションでドラッグ & ドロップを設定しています。からカスタム データを取得しようとすると、JavaDoc stuggestの代わりにDragboardが取得されます。このバイト バッファーは、元のデータ型にキャストできません。java.nio.HeapByteBufferObject

私は Scala で作業しているので、構文は少し異なりますが、理解できます。HeapByteBufferただし、通常の代わりにこれを取得しているのは、おそらく Scala にいるためですObjectか?

詳細

では、ドラッグ アンド ドロップできる JavaFX コントロールを作成します。Stringaと a MyObject;を付けます。はString取得できますが、 は取得MyObjectできません。
単純な文字列をドラッグボードに接続する簡単な方法があることは承知しています。これはMyObject、ドラッグボードからも取得できることを示す単なる例です。

ここでは、ドラッグできるカスタム コンポーネントを作成します。MyObjectドラッグすると、aと aの 2 つのオブジェクトがドラッグボードにアタッチされます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 のバニラ 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 に答える