在scala中使用条件逻辑绑定函数

时间:2013-07-03 06:12:22

标签: function scala binding scalafx

我是来自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

提前感谢您的帮助。

2 个答案:

答案 0 :(得分: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

我认为可以通过适应javafx.beans.binding包的可用类的类型参数来概括createXXXBinding,但我不确定这是一项简单的任务,因为类层次结构没有帮助。

答案 1 :(得分:1)

JavaFX2 +和ScalaFX允许您根据BooleanPropertyBooleanBinding动态切换两个绑定属性。这可以使用when构造来实现。你的coode

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

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

{{1}}