0

在 ScalaFX 中,如果我将 TreeCell 拖放到包含 TreeView 之外的控件上,则会播放一个简短的动画,显示拖动的项目返回到其原始位置。

如果我将 TreeCell 放到应用程序之外,也会发生同样的情况 - 例如放到桌面上。

如果我将 TreeCell 放到不应被接受的位置的包含 TreeView 上,我希望播放相同的动画,但设置:

event.dropCompleted = false

不足以产生这种效果。

有没有办法从 TreeCell 的 onDragDropped 事件处理程序中播放放置失败的动画?

编辑

根据要求添加了代码示例。将一个条目拖放到控件外,您将看到放置失败的动画。将一个条目拖放到列表下方,动画不会播放。问题是如何让动画在第二种情况下播放。

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