JavaFX vs ScalaFX NumberBindings

by 10/24/2012 02:30:00 PM 2 comments
I am working my way through Pro JavaFX 2 and writing the examples from the book in ScalaFX. One example really hammered home how much more concise ScalaFX code can be. Below is the example code in both ScalaFX and JavaFX. The code uses JavaFX bindings to calculate the area of a triangle in the Cartesian plane with vertices (x1, y1), (x2, y2), (x3, y3) using this formula:
 Area = (x1*y2 + x2*y3 + x3*y1 – x1*y3 – x2*y1 – x3*y2) / 2

JavaFX

import javafx.beans.binding.Bindings; 
import javafx.beans.binding.NumberBinding; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
 
public class TriangleAreaExample { 
    public static void main(String[] args) { 
        IntegerProperty x1 = new SimpleIntegerProperty(0); 
        IntegerProperty y1 = new SimpleIntegerProperty(0); 
        IntegerProperty x2 = new SimpleIntegerProperty(0); 
        IntegerProperty y2 = new SimpleIntegerProperty(0); 
        IntegerProperty x3 = new SimpleIntegerProperty(0); 
        IntegerProperty y3 = new SimpleIntegerProperty(0); 
 
        final NumberBinding x1y2 = Bindings.multiply(x1, y2); 
        final NumberBinding x2y3 = Bindings.multiply(x2, y3); 
        final NumberBinding x3y1 = Bindings.multiply(x3, y1); 
        final NumberBinding x1y3 = Bindings.multiply(x1, y3); 
        final NumberBinding x2y1 = Bindings.multiply(x2, y1); 
        final NumberBinding x3y2 = Bindings.multiply(x3, y2); 
 
        final NumberBinding sum1 = Bindings.add(x1y2, x2y3); 
        final NumberBinding sum2 = Bindings.add(sum1, x3y1); 
        final NumberBinding sum3 = Bindings.add(sum2, x3y1); 
        final NumberBinding diff1 = Bindings.subtract(sum3, x1y3); 
        final NumberBinding diff2 = Bindings.subtract(diff1, x2y1); 
        final NumberBinding determinant = Bindings.subtract(diff2, x3y2); 
        final NumberBinding area = Bindings.divide(determinant, 2.0D); 

        x1.set(0); y1.set(0); 
        x2.set(6); y2.set(0); 
        x3.set(4); y3.set(3); 
 
        printResult(x1, y1, x2, y2, x3, y3, area); 
 
        x1.set(1); y1.set(0); 
        x2.set(2); y2.set(2); 
        x3.set(0); y3.set(1); 
 
        printResult(x1, y1, x2, y2, x3, y3, area); 
    } 
 
    private static void printResult(IntegerProperty x1, IntegerProperty y1, 
                                    IntegerProperty x2, IntegerProperty y2, 
                                    IntegerProperty x3, IntegerProperty y3, 
                                    NumberBinding area) { 
        System.out.println("For A(" + 
                x1.get() + "," + y1.get() + "), B(" + 
                x2.get() + "," + y2.get() + "), C(" + 
                x3.get() + "," + y3.get() + "), the area of triangle ABC is " + 
                area.getValue()); 
    } 

JavaFX using a Fluent API

import javafx.beans.binding.Bindings; 
import javafx.beans.binding.NumberBinding; 
import javafx.beans.binding.StringExpression; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
 
public class TriangleAreaFluentExample { 
    public static void main(String[] args) { 
        IntegerProperty x1 = new SimpleIntegerProperty(0); 
        IntegerProperty y1 = new SimpleIntegerProperty(0); 
        IntegerProperty x2 = new SimpleIntegerProperty(0); 
        IntegerProperty y2 = new SimpleIntegerProperty(0); 
        IntegerProperty x3 = new SimpleIntegerProperty(0); 
        IntegerProperty y3 = new SimpleIntegerProperty(0); 
 
        final NumberBinding area = x1.multiply(y2) 
                .add(x2.multiply(y3)) 
                .add(x3.multiply(y1)) 
                .subtract(x1.multiply(y3)) 
                .subtract(x2.multiply(y1)) 
                .subtract(x3.multiply(y2)) 
                .divide(2.0D); 
 
        StringExpression output = Bindings.format( 
                "For A(%d,%d), B(%d,%d), C(%d,%d), the area of triangle ABC is %3.1f", 
                x1, y1, x2, y2, x3, y3, area); 
 
        x1.set(0); y1.set(0); 
        x2.set(6); y2.set(0); 
        x3.set(4); y3.set(3); 
 
        System.out.println(output.get()); 
        x1.set(1); y1.set(0); 
        x2.set(2); y2.set(2); 
        x3.set(0); y3.set(1); 
 
        System.out.println(output.get()); 
    }
}

ScalaFX

import scalafx.beans.property.IntegerProperty

object TriangleAreaExample extends App {

  val x1 = IntegerProperty(0)
  val y1 = IntegerProperty(0)
  val x2 = IntegerProperty(0)
  val y2 = IntegerProperty(0)
  val x3 = IntegerProperty(0)
  val y3 = IntegerProperty(0)

  val area = (x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x2 * y1 - x3 * y2) / 2D

  x1() = 0
  y1() = 0
  x2() = 6
  y2() = 0
  x3() = 4
  y3() = 3
  printResult

  x1() = 1
  y1() = 0
  x2() = 2
  y2() = 2
  x3() = 0
  y3() = 1
  printResult

  def printResult = {
    println("For A(" + x1() + ", " + y1()  + "), " +
        "B(" + x2() + ", " + y2()  + "), " +
        "C(" + x3() + ", " + y3()  + "), " +
        "the area of triangle ABC is " + area())
  }

}

Brian Schlining

Developer

Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

2 comments:

Rafael U. C. Afonso said...

Brian:

Some months ago I begin a project called ProScalaFX (https://github.com/rafonso/ProScalaFX/). There is even a version of the example that you showed above (https://github.com/rafonso/ProScalaFX/blob/master/src/proscalafx/ch03/TriangleAreaExample.scala). However I must admit that in print method I used ObservableValue's get instead "()" method.
Unfortunately, I am not being able to update the project. And even some examples commited need to be improved. If you, or other intrested, want make a project clone or even commit some code, you are welcome.

Thanks,

Rafel Afonso

Brian Schlining said...

Hi Rafael,
Thanks for the pointer to the project. If I get some time, I'll clone the project and update it as needed.