0

ScalaFX では、含まれている TreeView 以外のコントロールに TreeCell をドロップすると、ドラッグされたアイテムが元の位置に戻る短いアニメーションが再生されます。

TreeCell をアプリケーションの外 (デスクトップなど) にドロップすると、同じことが起こります。

TreeCell を含む TreeView の受け入れられない場所にドロップすると、同じアニメーションを再生したいのですが、次のように設定します。

event.dropCompleted = false

この効果を生み出すには十分ではありません。

TreeCell の onDragDropped イベント ハンドラ内からドロップ失敗アニメーションを再生する方法はありますか?

編集

リクエストに応じてコード サンプルを追加しました。エントリをドラッグしてコントロールの外にドロップすると、ドロップ失敗のアニメーションが表示されます。エントリをリストの下にドラッグ アンド ドロップすると、アニメーションが再生されません。問題は、2 番目のケースでアニメーションを再生する方法です。

import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.paint.Color
import scalafx.scene.layout.Pane
import scalafx.Includes._
import scalafx.scene.input.{TransferMode, DataFormat, DragEvent, MouseEvent}
import scalafx.scene.control._
import javafx.scene.control.{TreeItem => jfxTreeItem}
import java.nio.ByteBuffer
import java.util
import scalafx.beans.value.ObservableValue


class StringRootItem(text: String) extends TreeItem[String](text) {
  override def toString() = text
}

class StringTreeItem(text: String) extends TreeItem[String](text) {
  override def toString() = text
}

object DragAndDropControl {
  def apply(rootNodeName: String, entries: List[String]): DragAndDropControl = {
    val rootItem = new StringRootItem(rootNodeName)
    rootItem.setExpanded(true)

    val children = rootItem.getChildren

    entries.foreach(entry => {
      children.add(new StringTreeItem(entry))
    })

    new DragAndDropControl(rootItem)
  }
}

class DragAndDropControl(rootItem: StringRootItem) extends TreeView[String](rootItem) {
  showRoot = false

  cellFactory = (tree: TreeView[String]) => {
    new StringDragAndDropCell(tree)
  }

  object StringDragAndDropCell {
    val customFormat: DataFormat = new DataFormat("string.entry.custom")

    var transferItem: TreeItem[String] = null

    def toBuffer(entry: String): ByteBuffer = ByteBuffer.allocate(10)


    def fromBuffer(buffer: ByteBuffer): String = null
  }

  class StringDragAndDropCell(tree: TreeView[String]) extends TreeCell[String] {
    import StringDragAndDropCell._

    private var stringEntry: String = null

    onDragDetected = (event: MouseEvent) => {
      val db = startDragAndDrop(TransferMode.MOVE)

      import scala.collection.JavaConversions._
      if ((treeItem ne null) && (treeItem.value ne null) && (treeItem.value.getValue ne null)) {
        transferItem = treeItem.value

        val content: Map[javafx.scene.input.DataFormat, AnyRef] = Map(customFormat.delegate -> toBuffer(transferItem.value()))
        val contentMap: util.Map[javafx.scene.input.DataFormat, AnyRef] = mapAsJavaMap(content)

        db.setContent(contentMap)
      }

      event.consume()
    }

    onDragOver = (event: DragEvent) => {
      val db = event.getDragboard
      if (db.hasContent(customFormat))
        event.acceptTransferModes(TransferMode.MOVE)

      event.consume()
    }

    onDragDone = (event: DragEvent) => {
      if (event.transferMode == TransferMode.MOVE)
        event.dragboard.clear()

      event.consume()
    }

    onDragDropped = (event: DragEvent) => {
      val db = event.getDragboard
      var success = false
      if (db.hasContent(customFormat))
        success = stringEntry ne null

      if (success)
        if (event.gestureSource != event.delegate.getGestureTarget) {
          treeItem().getParent.getChildren.removeAll(transferItem)
          treeItem().getParent.getChildren.add(index(), transferItem)
        }

      event.dropCompleted = success

      event.consume()
    }

    /*
     * Change handler for the treeItem property.
     *
     * The treeItem property is set by JavaFX after construction and at any time when the cell is recycled for UI virtualization.
     *
     * The text property must be updated when the treeItem is set in order for the cell to render correctly (without this the cell will appear blank.)
     */
    super.treeItem.onChange((observable: ObservableValue[jfxTreeItem[String], jfxTreeItem[String]], oldValue: jfxTreeItem[String], newValue: jfxTreeItem[String]) => {
      if (newValue ne null) {
        stringEntry = newValue.getValue

        text = stringEntry
      }
      else
        stringEntry = null
    })

    override def toString(): String = {
      if (stringEntry == null)
        null
      else
        s"ScalaFX string tree cell ${stringEntry.toString}"
    }
  }
}


object TestDragAndDrop extends JFXApp
{
  println("javafx.runtime.version: " + System.getProperties.get("javafx.runtime.version"))
  println("java.runtime.version:   " + System.getProperties.get("java.runtime.version"))

  stage = new JFXApp.PrimaryStage {
    title = "Test Drag and Drop"
    width = 600
    height = 472
    scene = new Scene {
      fill = Color.LIGHTGREEN
      root = new Pane {
        content = DragAndDropControl("Numbers", List("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"))
      }
    }
  }
}
4

0 に答える 0