我正在尝试为 ScalaFX 应用程序中的布局更改设置动画,类似于这个问题。场景包括一个主窗格。每次单击它时,都会在其中添加另一个窗格(“儿子”)(实际上是在其中的 FlowPane 内)。窗格添加应该“推高”以前的儿子,如果需要,“挤压”以前的儿子(直到他们的最小高度)。
有两个问题:
- 动画不流畅。有时,当添加儿子或调整窗口大小时,会出现闪烁(“故障”),其中节点的位置和/或比例会暂时不正确。我尝试按照引用的答案中的建议设置初始值,但似乎没有解决它。
- 通过拖动底部边缘调整窗口大小时,移动动画从当前位置正确开始。但是,当拖动顶部边缘时,有一个跳跃是初始位置。
代码如下:
import scalafx.Includes._
import scalafx.scene.input.MouseEvent
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.Scene
import scalafx.animation.{ScaleTransition, TranslateTransition}
import scalafx.geometry.Pos
import scalafx.scene.control.ScrollPane
import scalafx.scene.layout._
import scalafx.util.Duration
object Main extends JFXApp {
stage = new PrimaryStage { scene = new Scene (new NodePane, 800, 600) }
}
class NodePane(isExternal: Boolean = true) extends BorderPane {
def makeMargin = new FlowPane {
prefHeight = 30
minHeight = 10
}
top = makeMargin
center = if (isExternal) new SonsPane() else new EmptySonsPane()
bottom = makeMargin
}
class SonsPane extends ScrollPane {
val vbox = new VBox {
fitToHeight = true
fitToWidth = true
alignment = Pos.Center
}
content = vbox
onMouseClicked = (e: MouseEvent) => vbox.content.add(makeSonPane())
def makeSonPane() = {
new NodePane(isExternal = false) {
prefHeight = 150
// initial initialization
// scaleY = 0.1
var prevPos = layoutY.value
var prevHeight = height.value
// change events
layoutY.onChange {
if (prevPos != 0) {
val translation = new TranslateTransition(Duration(600), this) {
fromY = prevPos - layoutY.value
toY = 0
}
translateY = layoutY.value - prevPos
translation.play()
}
prevPos = layoutY.value
}
height.onChange {
val scaling = new ScaleTransition(Duration(600), this) {
fromY = prevHeight / height.value
toY = 1
}
scaleY = prevHeight / height.value
scaling.play()
prevHeight = height.value
}
}
}
}
class EmptySonsPane extends FlowPane {
style = "-fx-border-color: black; -fx-background-color: yellow; -fx-background-opacity: 0.5"
minHeight = 100
}