2

我是来自 JavaFX 1.3 的 scala 新手,这是我在 stackoverflow 中的第一篇文章

在 JavaFX 1.3 我可以做这样的事情

property : bind if (condition) value1 else value2

在 Scala 中,我尝试做这样的事情:

property <== function1

def function1() = {
  if (condition)
    value1
  else
    value2
}

但是,它似乎不是动态工作的。当舞台出现时,函数条件中的表达式只计算一次。我有点期待该表达式中的值是实时评估的。

具体来说,我想将某些东西调整到某个限制,并且我正在使用绑定来实现它。因此,我希望绑定函数继续评估表达式,并在我调整其他事物的大小时给我适当的宽度。

无论如何,我将在下面粘贴实际代码:

var stageWidth = DoubleProperty(0)
var stageHeight = DoubleProperty(0)

stageWidth <== stage.scene.width
stageHeight <== stage.scene.height

var origStageWidth = DoubleProperty(stage.scene.width.toDouble)
val origStageHeight = DoubleProperty(stage.scene.height.toDouble)

val origTextClipperWidth = DoubleProperty(textClipper.width.toDouble)
val origTextClipperHeight = DoubleProperty(textClipper.height.toDouble)
val minWidth = DoubleProperty(100)

val origButtonWidth = DoubleProperty(button.prefWidth.toDouble)

textClipper.width <== resize

def resize() ={
    var boolResult = (stageWidth - origStageWidth) + origTextClipperWidth > minWidth
    if (boolResult.value) {
        (stageWidth - origStageWidth) + origTextClipperWidth
    } else {
        minWidth
    }
}

textClipper.height <== (stageHeight - origStageHeight) + origTextClipperHeight

在此先感谢您的帮助。

4

2 回答 2

2

JavaFX2+ 和ScalaFX允许您基于 aBooleanProperty或动态切换两个绑定属性BooleanBinding。这可以使用when构造来实现。你的代码

property : bind if (condition) value1 else value2

在 ScalaFX 中可以表示为:

property <== when (condition) choose value1 otherwise value2

在您的具体示例中,假设我们创建一个width包含基于条件动态计算的宽度的属性boolResult

val width = DoubleProperty(0)

width属性使用when构造绑定到条件表达式

width <== when(boolResult) choose ((stageWidth - origStageWidth) + origTextClipperWidth) otherwise minWidth

boolResult值是true第一部分(选择后)width时,它是分配false后的部分otherwise。这是一个完整的示例,显示了这一点:

import scalafx.Includes._
import scalafx.beans.property.DoubleProperty

object ConditionalBindigDemo extends App {

  val stageWidth = DoubleProperty(200)
  val origStageWidth = DoubleProperty(100)

  val origTextClipperWidth = DoubleProperty(20)
  val minWidth = DoubleProperty(50)

  val boolResult = (stageWidth - origStageWidth) + origTextClipperWidth > minWidth
  val width = DoubleProperty(0)
  width <== when(boolResult) choose ((stageWidth - origStageWidth) + origTextClipperWidth) otherwise minWidth

  // Simple test
  printState()
  stageWidth() = 150
  printState()
  stageWidth() = 100
  printState()
  stageWidth() = 50
  printState()

  def printState() {
    println("stageWidth: " + stageWidth() + ", origStageWidth: " + origStageWidth() + ", width: " + width())
  }
}

当你运行它时,你会得到输出:

stageWidth: 200.0, origStageWidth: 100.0, resizeWidth: 120.0
stageWidth: 150.0, origStageWidth: 100.0, resizeWidth: 70.0
stageWidth: 100.0, origStageWidth: 100.0, resizeWidth: 50.0
stageWidth: 50.0, origStageWidth: 100.0, resizeWidth: 50.0
于 2013-07-21T04:42:07.310 回答
1

标准函数/方法不是,scalafx.beans.Observable因此它没有必要的“挂钩”来使其绑定无效。

前段时间我做了一些方法来简化绑定创建,就是为了这个目的。

以下代码用于使函数绑定到字符串值

import scalafx.Includes._
import scalafx.beans.binding.StringBinding
import scalafx.beans.Observable
import scalafx.collections._
import javafx.collections.ObservableList
import javafx.beans.{ binding => jfxbb }
import jfxbb.ListBinding

def createStringBinding(dependency: Observable*)(computeFunction: => String): StringBinding = 
  new jfxbb.StringBinding {
  //invalidated when the passed dependency becomes invalid
  dependency.foreach(this.bind(_))
  //use the function to compute the new value
  override def computeValue: String = computeFunction
}

在您的情况下,您应该进行双重绑定

//THIS CODE IS NOT TESTED, MAYBE IT NEEDS A LITTLE TWEAKING

def createDoubleBinding(dependency: Observable*)(computeFunction: => Double): DoubleBinding = 
  new jfxbb.DoubleBinding {
  //invalidated when the passed dependency becomes invalid
  dependency.foreach(this.bind(_))
  //use the function to compute the new value
  override def computeValue: Double = computeFunction
}

//and use it like
val resize = createDoubleBinding(
  stageWidth,
  stageHeight,
  origStageWidth,
  origStageHeight,
  minWidth,
  origButtonWidth) {
    var boolResult = (stageWidth - origStageWidth) + origTextClipperWidth > minWidth
    if (boolResult.value) {
      (stageWidth - origStageWidth) + origTextClipperWidth
    } else {
      minWidth
    }
}

textClipper.width <== resize

我想可以用适应包的可用类的类型参数来概括 createXXXBinding javafx.beans.binding,但我不确定这会是一件容易的事,因为类层次结构没有帮助......

于 2013-07-03T10:28:56.020 回答