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
}

ただし、動的に動作しているようには見えません。関数の条件の式は、ステージが表示されたときに 1 回だけ評価されます。その式の値がリアルタイムで評価されることを期待していました。

具体的には、何かを特定の制限までサイズ変更したいので、バインディングを使用してそれを達成しています。したがって、バインドされた関数が式を評価し続け、他のもののサイズを変更するときに何かの適切な幅を与えてほしい.

とにかく、実際のコードを以下に貼り付けます。

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+ とScalaFXBooleanPropertyを使用すると、またはに基づいて 2 つのバインドされたプロパティを動的に切り替えることができますBooleanBindingwhenこれは、コンストラクトを使用して実現できます。あなたのコーデ

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

boolResultvalue がtrue最初の部分の場合(選択後) が割り当てられた後の部分のwidth場合に割り当てられます。これが実際に行われていることを示す完全な例を次に示します。falseotherwise

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 に答える