SlideShare una empresa de Scribd logo
1 de 77
Descargar para leer sin conexión
Hacking JavaFX with Groovy, Clojure,
Scala, and Visage
                       Stephen Chin
                       Java Evangelist, Oracle
                       stephen.chin@oracle.com
                       tweet: @steveonjava
Meet the Presenter

           Stephen Chin
                                     >   Java Evangelist, Oracle
                                     >   Author, Pro JavaFX Platform 2
      Family Man
                                     >   Open Source Hacker
                                            JFXtras
                                            ScalaFX
                      Motorcyclist          Visage
                                     >   User Group Co-Leader
                                            Silicon Valley JavaFX
                                             User Group
                                            Streamed Live!
Safe Harbor Statement
The following is intended to outline our general product
direction. It is intended for information purposes only, and
may not be incorporated into any contract. It is not a
commitment to deliver any material, code, or functionality,
and should not be relied upon in making purchasing
decisions. The development, release, and timing of any
features or functionality described for Oracle’s products
remains at the sole discretion of Oracle.
JavaFX 2.0 Platform
Immersive Application Experience
Leverage your Java skills with modern JavaFX
APIs
>   Cross-platform Animation, Video, Charting
>   Integrate Java, JavaScript, and HTML5 in the
    same application
>   New graphics stack takes advantage of
    hardware acceleration for 2D and 3D
    applications
>   Use your favorite IDE: NetBeans, Eclipse,
    IntelliJ, etc.
JavaFX With Java
Programming Languages
>   JavaFX 2.0 APIs are now in Java
       Pure Java APIs for all of JavaFX
       Binding and Sequences exposed as Java APIs
       FXML Markup for tooling
>   Embrace all JVM languages
       Groovy, Scala, Clojure, JRuby
       Fantom, Mira, Gosu, Jython, etc.
>   JavaFX Script is no longer supported by Oracle
       Existing JavaFX Script based applications will continue to run
       Visage is the open-source successor to the JavaFX Script language
Vanishing Circles




                    7
Vanishing Circles in Java
public class VanishingCircles extends Application {

    public static void main(String[] args) {
      Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
      primaryStage.setTitle("Vanishing Circles");
      Group root = new Group();
      Scene scene = new Scene(root, 800, 600, Color.BLACK);
      List<Circle> circles = new ArrayList<Circle>();
      for (int i = 0; i < 50; i++) {
        final Circle circle = new Circle(150);
        circle.setCenterX(Math.random() * 800);
        circle.setCenterY(Math.random() * 600);
        circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2));
                                                                                              40 Lines
        circle.setEffect(new BoxBlur(10, 10, 3));
        circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
          public void handle(MouseEvent t) {
            KeyValue collapse = new KeyValue(circle.radiusProperty(), 0);
                                                                                              1299 Characters
            new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play();
          }
        });
        circle.setStroke(Color.WHITE);
        circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty())
          .then(4)
          .otherwise(0));
        circles.add(circle);
      }
      root.getChildren().addAll(circles);
      primaryStage.setScene(scene);
      primaryStage.show();

        Timeline moveCircles = new Timeline();
        for (Circle circle : circles) {
          KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800);
          KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600);
          moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY));
        }
        moveCircles.play();
    }
}




                                                                                                                8
Application Skeleton
public class VanishingCircles extends Application {
  public static void main(String[] args) {
    Application.launch(args);
  }
  @Override
  public void start(Stage primaryStage) {
    primaryStage.setTitle("Vanishing Circles");
    Group root = new Group();
    Scene scene = new Scene(root, 800, 600, Color.BLACK);
    [create the circles…]
    root.getChildren().addAll(circles);
    primaryStage.setScene(scene);
    primaryStage.show();
    [begin the animation…]
  }
}
Create the Circles
List<Circle> circles = new ArrayList<Circle>();
for (int i = 0; i < 50; i++) {
  final Circle circle = new Circle(150);
  circle.setCenterX(Math.random() * 800);
  circle.setCenterY(Math.random() * 600);
  circle.setFill(new Color(Math.random(), Math.random(),
                           Math.random(), .2));
  circle.setEffect(new BoxBlur(10, 10, 3));
  circle.setStroke(Color.WHITE);
  [setup binding…]
  [setup event listeners…]
  circles.add(circle);
}

                                                           10
Setup Binding
circle.strokeWidthProperty().bind(Bindings
   .when(circle.hoverProperty())
   .then(4)
   .otherwise(0)
);




                                             11
Setup Event Listeners
circle.addEventHandler(MouseEvent.MOUSE_CLICKED,
                        new EventHandler<MouseEvent>() {
  public void handle(MouseEvent t) {
    KeyValue collapse = new KeyValue(circle.radiusProperty(), 0);
    new Timeline(new KeyFrame(Duration.seconds(3),
                              collapse)).play();
  }
});




                                                                    12
Begin the Animation
Timeline moveCircles = new Timeline();
for (Circle circle : circles) {
  KeyValue moveX = new KeyValue(circle.centerXProperty(),
                                Math.random() * 800);
  KeyValue moveY = new KeyValue(circle.centerYProperty(),
                                Math.random() * 600);
  moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40),
                                              moveX, moveY));
}
moveCircles.play();


                                                                  13
JavaFX With Groovy
Features of Groovy
>   Modern language
       Closures
       AST Transforms
       Strongly typed dynamic language

>   Tight integration with Java
       Very easy to port from Java to Groovy

>   Declarative syntax with GroovyFX Builders
       Familiar to Groovy and JavaFX Script developers
Java vs. GroovyFX DSL
public class VanishingCircles extends Application {                                           GroovyFX.start { primaryStage ->
                                                                                                def sg = new SceneGraphBuilder()
    public static void main(String[] args) {                                                    def rand = new Random().&nextInt
      Application.launch(args);                                                                 def circles = []
    }
                                                                                                  sg.stage(title: 'Vanishing Circles', show: true) {
    @Override                                                                                       scene(fill: black, width: 800, height: 600) {
    public void start(Stage primaryStage) {                                                           50.times {
      primaryStage.setTitle("Vanishing Circles");                                                       circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white,
      Group root = new Group();                                                                                  strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
      Scene scene = new Scene(root, 800, 600, Color.BLACK);                                               fill rgb(rand(255), rand(255), rand(255), 0.2)
      List<Circle> circles = new ArrayList<Circle>();                                                     effect boxBlur(width: 10, height: 10, iterations: 3)
      for (int i = 0; i < 50; i++) {                                                                      onMouseClicked { e ->


                                                                                                                     29 Lines
        final Circle circle = new Circle(150);                                                              timeline {

                  40 Lines
        circle.setCenterX(Math.random() * 800);
        circle.setCenterY(Math.random() * 600);
        circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2));
        circle.setEffect(new BoxBlur(10, 10, 3));                                                       }
                                                                                                          }
                                                                                                              at(3.s) { change e.source.radiusProperty() to 0 }
                                                                                                            }.play()




                  1299 Characters
        circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
          public void handle(MouseEvent t) {
            KeyValue collapse = new KeyValue(circle.radiusProperty(), 0);
            new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play();
                                                                                                    }
                                                                                                      }
                                                                                                                     671 Characters
                                                                                                      timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
          }                                                                                             circles.each { circle ->
        });                                                                                               at (40.s) {
        circle.setStroke(Color.WHITE);                                                                      change circle.centerXProperty() to rand(800)
        circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty())                             change circle.centerYProperty() to rand(600)
          .then(4)                                                                                        }
          .otherwise(0));                                                                               }
        circles.add(circle);                                                                          }.play()
      }                                                                                           }
      root.getChildren().addAll(circles);                                                     }
      primaryStage.setScene(scene);
      primaryStage.show();

        Timeline moveCircles = new Timeline();
        for (Circle circle : circles) {
          KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800);
          KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600);
          moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY));
        }
        moveCircles.play();
    }
}




                                                                                                                                                                                                16
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []

    sg.stage(title: 'Vanishing Circles', show: true) {
      scene(fill: black, width: 800, height: 600) {
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white,
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          17
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []
                                       Builder for GroovyFX scene graphs
    sg.stage(title: 'Vanishing Circles', show: true) {
      scene(fill: black, width: 800, height: 600) {
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white,
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          18
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []

    sg.stage(title: 'Vanishing Circles', show: true) {
      scene(fill: black, width: 800, height: 600) {
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white, Declarative Stage definition
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          19
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []
                                Inline property definitions
    sg.stage(title: 'Vanishing Circles', show: true) {
      scene(fill: black, width: 800, height: 600) {
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white,
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          20
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []

    sg.stage(title: 'Vanishing Circles', show: true) {
      scene(fill: black, width: 800, height: 600) { Bind to properties
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white,
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          21
GroovyFX.start { primaryStage ->
  def sg = new SceneGraphBuilder()
  def rand = new Random().&nextInt
  def circles = []

    sg.stage(title: 'Vanishing Circles', show: Sequence Creation Via Loop
                                               true) {
      scene(fill: black, width: 800, height: 600) {
        50.times {
          circles << circle(centerX: rand(800), centerY: rand(600),
              radius: 150, stroke: white,
              strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) {
            fill rgb(rand(255), rand(255), rand(255), 0.2)
            effect boxBlur(width: 10, height: 10, iterations: 3)
          }
        }
      }
    }
}
                                                                          22
Animation in GroovyFX
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
  circles.each { circle ->
    at (40.s) {
      change circle.centerXProperty() to rand(800)
      change circle.centerYProperty() to rand(600)
    }
  }
}.play()




                                                                 23
Animation in GroovyFX
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
  circles.each { circle ->
    at (40.s) {
      change circle.centerXProperty() to rand(800)
      change circle.centerYProperty() to rand(600)
    }
  }                                   Easy animation syntax:
}.play()                             at (duration) {keyframes}




                                                                 24
Animation in GroovyFX
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
  circles.each { circle ->
    at (40.s) {
      change circle.centerXProperty() to rand(800)
      change circle.centerYProperty() to rand(600)
    }
  }
}.play()
                                      Key frame DSL



                                                                 25
Animation in GroovyFX
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
  circles.each { circle ->
    at (40.s) {
      change circle.centerXProperty() to rand(800) tween ease_both
      change circle.centerYProperty() to rand(600) tween linear
    }
  }
}.play()
                                            Optional easing




                                                                     26
Event Listeners in GroovyFX
>   Supported using the built-in Closure syntax
>   Optional arguments for event objects

onMouseClicked { e ->
  timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
  }.play()
}



                                                        27
Event Listeners in GroovyFX
>   Supported using the built-in Closure syntax
>   Optional arguments for event objects

onMouseClicked { MouseEvent e ->
  timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
  }.play()
}
                       Compact syntax
                          {body}
                                                        28
Event Listeners in GroovyFX
>   Supported using the built-in Closure syntax
>   Optional arguments for event objects          Optional event parameter
                                                       {event -> body}

onMouseClicked { MouseEvent e ->
  timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
  }.play()
}



                                                                             29
But wait, there is more Grooviness…   30
Properties in Java
public class Person {
 private StringProperty firstName;
 public void setFirstName(String val) { firstNameProperty().set(val); }
 public String getFirstName() { return firstNameProperty().get(); }
 public StringProperty firstNameProperty() {
   if (firstName == null)
     firstName = new SimpleStringProperty(this, "firstName");
   return firstName;
 }

    private StringProperty lastName;
    public void setLastName(String value) { lastNameProperty().set(value); }
    public String getLastName() { return lastNameProperty().get(); }
    public StringProperty lastNameProperty() {
      if (lastName == null) // etc.
    }
}


                                                                               31
Properties in GroovyFX
public class Person {
  @FXBindable String firstName;
  @FXBindable String lastName;
}




                                  32
Properties in GroovyFX
public class Person {
  @FXBindable String firstName;
  @FXBindable String lastName = “Smith”;
}

                                           Optional initializers




                                                                   33
TableView in Java
ObservableList<Person> items = ...
TableView<Person> tableView = new TableView<Person>(items);

TableColumn<Person,String> firstNameCol =
     new TableColumn<Person,String>("First Name");

firstNameCol.setCellValueFactory(
       new Callback<CellDataFeatures<Person, String>,
               ObservableValue<String>>() {
  public ObservableValue<String> call(CellDataFeatures<Person, String> p)
  {
    return p.getValue().firstNameProperty();
  }
});

tableView.getColumns().add(firstNameCol);
                                                                            34
TableView in GroovyFX
def dateFormat = new SimpleDateFormat("yyyy-MM-dd");

tableView(items: persons) {
  tableColumn(property: "name", text: "Name", prefWidth: 150)
  tableColumn(property: "age", text: "Age", prefWidth: 50)
  tableColumn(property: "gender", text: "Gender", prefWidth: 150)
  tableColumn(property: "dob", text: "Birth", prefWidth: 150,
         type: Date,
         converter: { from -> return dateFormat.format(from) })
}




                                                                    35
Layout in Java
TextField urlField = new TextField(“http://www.google.com”);
HBox.setHgrow(urlField, Priority.ALWAYS);

HBox hbox = new HBox();
hbox.getChildren().add(urlField);

WebView webView = new WebView();
VBox.setVgrow(webView, Priority.ALWAYS);

VBox vbox = new VBox();
vbox.getChildren().addAll(hbox, webView);




                                                               36
Layout in GroovyFX

sg.stage(title: "GroovyFX WebView Demo", show: true) {
  scene(fill: groovyblue, width: 1024, height: 800) {
     vbox {
       hbox(padding: 10, spacing: 5) {
          textField(“http://www.yahoo.com”, hgrow: "always")
          button("Go”)
       }
       webView(vgrow: "always")
     }
  }
}

                                                               37
Layout in GroovyFX




                     38
Layout in GroovyFX
gridPane(hgap: 5, vgap: 10, padding: 25) {
 columnConstraints(minWidth: 50, halignment: "right")
 columnConstraints(prefWidth: 250)
 label("Send Us Your Feedback", font: "24pt sanserif",
     row: 0, columnSpan: GridPane.REMAINING, halignment: "center",
     margin: [0, 0, 10])

    label("Name: ", row: 1, column: 0)
    textField(promptText: "Your name", row: 1, column: 1, hgrow: 'always')

    label("Email:", row: 2, column: 0)
    textField(promptText: "Your email", row: 2, column: 1, hgrow: 'always')

    label("Message:", row: 3, column: 0, valignment: "baseline")
    textArea(row: 3, column: 1, hgrow: "always", vgrow: "always")

    button("Send Message", row: 4, column: 1, halignment: "right")
}
                                                                              39
Layout in GroovyFX




                     40
GroovyFX Supports…




                     41
JavaFX With Clojure




        Artwork by Augusto Sellhorn   http://sellmic.com/




                                                            42
A Little About         Clojure
>   Started in 2007 by Rich Hickey
>   Functional Programming Language
>   Derived from LISP
>   Optimized for High Concurrency

                (def hello (fn [] "Hello world"))
                (hello)

>   … and looks nothing like Java!

                                                    43
Clojure Syntax in One Slide
                   Symbols                                               Collections
                                                                         (commas optional)

 >   numbers – 2.178                                 >  Lists
 >   ratios – 355/113                                (1, 2, 3, 4, 5)
 >   strings – “clojure”, “rocks”                    > Vectors

 >   characters – a b c d                        [1, 2, 3, 4, 5]
 >   symbols – a b c d                               > Maps

 >   keywords – :alpha :beta                         {:a 1, :b 2, :c 3, :d 4}
 >   boolean – true, false                           > Sets

 >   null - nil                                      #{:a :b :c :d :e}

             (plus macros that are syntactic sugar wrapping the above)
                                                                                             44
Clojure GUI Example
(defn javafxapp []
  (let [stage (Stage. "JavaFX Stage")
        scene (Scene.)]
    (.setFill scene Color/LIGHTGREEN)
    (.setWidth stage 600)
    (.setHeight stage 450)
    (.setScene stage scene)
    (.setVisible stage true)))
(javafxapp)

                                        45
Refined Clojure GUI Example
(defn javafxapp []
  (doto (Stage. "JavaFX Stage")
    (.setWidth 600)
    (.setHeight 450)
    (.setScene (doto (Scene.)
      (.setFill Color/LIGHTGREEN)
      (.setContent (list (doto (Rectangle.)
        (.setX 25)
        (.setY 40)
        (.setWidth 100)
        (.setHeight 50)
        (.setFill Color/RED))))))
    (.setVisible true)))
(javafxapp)

                                              46
Refined Clojure GUI Example
(defn javafxapp []
  (doto (Stage. "JavaFX Stage")
    (.setWidth 600)                           Doto allows nested data
    (.setHeight 450)
    (.setScene (doto (Scene.)                        structures
      (.setFill Color/LIGHTGREEN)
      (.setContent (list (doto (Rectangle.)
        (.setX 25)
        (.setY 40)
        (.setWidth 100)
        (.setHeight 50)
        (.setFill Color/RED))))))
    (.setVisible true)))
(javafxapp)

                                                                        47
Closures in Clojure
>   Inner classes can be created using proxy




    (.addListener hoverProperty
      (proxy [ChangeListener] []
        (handle [p, o, v]
          (.setFill rect
            (if (.isHover rect) Color/GREEN Color/RED)))))




                                                             48
Closures in Clojure
>   Inner classes can be created using proxy
                                         Proxy form:
                           (proxy [class] [args] fs+)
                           f => (name [params*] body)
    (.addListener hoverProperty
      (proxy [ChangeListener] []
        (handle [p, o, v]
          (.setFill rect
            (if (.isHover rect) Color/GREEN Color/RED)))))




                                                             49
JavaFX With Scala




                    50
What is Scala
     2001                             2006
     • Scala Started                  • Scala v2.0




                       2003/2004                     2011
                       • Scala v1.0                  • Scala 2.9.2 (latest)



>   Started in 2001 by Martin Odersky
>   Compiles to Java bytecodes
>   Pure object-oriented language
>   Also a functional programming language
                                                                              51
Java vs. Scala DSL
public class VanishingCircles extends Application {                                           object VanishingCircles extends JFXApp {
                                                                                                var circles: Seq[Circle] = null
    public static void main(String[] args) {                                                    stage = new Stage {
      Application.launch(args);                                                                   title = "Vanishing Circles"
    }                                                                                             width = 800
                                                                                                  height = 600
    @Override                                                                                     scene = new Scene {
    public void start(Stage primaryStage) {                                                         fill = BLACK
      primaryStage.setTitle("Vanishing Circles");                                                   circles = for (i <- 0 until 50) yield new Circle {
      Group root = new Group();                                                                       centerX = random * 800
      Scene scene = new Scene(root, 800, 600, Color.BLACK);                                           centerY = random * 600
      List<Circle> circles = new ArrayList<Circle>();                                                 radius = 150
      for (int i = 0; i < 50; i++) {                                                                  fill = color(random, random, random, .2)
        final Circle circle = new Circle(150);                                                        effect = new BoxBlur(10, 10, 3)

                  40 Lines
        circle.setCenterX(Math.random() * 800);
        circle.setCenterY(Math.random() * 600);
        circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2));
        circle.setEffect(new BoxBlur(10, 10, 3));
                                                                                                                 33 Lines
                                                                                                      strokeWidth <== when (hover) then 4 otherwise 0
                                                                                                      stroke = WHITE
                                                                                                      onMouseClicked = {
                                                                                                        Timeline(at (3 s) {radius -> 0}).play()


                  1299 Characters
        circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
          public void handle(MouseEvent t) {
            KeyValue collapse = new KeyValue(circle.radiusProperty(), 0);
            new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play();                     }
                                                                                                    }
                                                                                                      }
                                                                                                                 591 Characters
                                                                                                    content = circles

          }                                                                                     }
        });
        circle.setStroke(Color.WHITE);                                                            new Timeline {
        circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty())                     cycleCount = INDEFINITE
          .then(4)                                                                                  autoReverse = true
          .otherwise(0));                                                                           keyFrames = for (circle <- circles) yield at (40 s) {
        circles.add(circle);                                                                          Set(
      }                                                                                                 circle.centerX -> random * stage.width,
      root.getChildren().addAll(circles);                                                               circle.centerY -> random * stage.height
      primaryStage.setScene(scene);                                                                   )
      primaryStage.show();                                                                          }
                                                                                                  }.play();
        Timeline moveCircles = new Timeline();                                                }
        for (Circle circle : circles) {
          KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800);
          KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600);
          moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY));
        }
        moveCircles.play();
    }
}




                                                                                                                                                            52
object VanishingCircles extends JFXApp {
  stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
      fill = BLACK
      children = for (i <- 0 until 50) yield new Circle {
        centerX = random * 800
        centerY = random * 600
        radius = 150
        fill = color(random, random, random, 0.2)
        effect = new BoxBlur(10, 10, 3)
      }
    }
  }
}
                                                            53
object VanishingCircles extends JFXApp {
  stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height Base class for JavaFX applications
            = 600
    scene = new Scene {
      fill = BLACK
      children = for (i <- 0 until 50) yield new Circle {
        centerX = random * 800
        centerY = random * 600
        radius = 150
        fill = color(random, random, random, 0.2)
        effect = new BoxBlur(10, 10, 3)
      }
    }
  }
}
                                                            54
object VanishingCircles extends JFXApp {
  stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {               Declarative Stage definition
      fill = BLACK
      children = for (i <- 0 until 50) yield new Circle {
        centerX = random * 800
        centerY = random * 600
        radius = 150
        fill = color(random, random, random, 0.2)
        effect = new BoxBlur(10, 10, 3)
      }
    }
  }
}
                                                                     55
object VanishingCircles extends JFXApp {
  stage = new Stage {
    title = "Disappearing Circles"
    width = 800                          Inline property definitions
    height = 600
    scene = new Scene {
      fill = BLACK
      children = for (i <- 0 until 50) yield new Circle {
        centerX = random * 800
        centerY = random * 600
        radius = 150
        fill = color(random, random, random, 0.2)
        effect = new BoxBlur(10, 10, 3)
      }
    }
  }
}
                                                                       56
object VanishingCircles extends JFXApp {
  stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600                      Sequence Creation Via Loop
    scene = new Scene {
      fill = BLACK
      children = for (i <- 0 until 50) yield new Circle {
        centerX = random * 800
        centerY = random * 600
        radius = 150
        fill = color(random, random, random, 0.2)
        effect = new BoxBlur(10, 10, 3)
      }
    }
  }
}
                                                                   57
Binding in Scala
Infix Addition/Subtraction/Multiplication/Division:
height <== rect1.height + rect2.height
Aggregate Operators:
width <== max(rect1.width, rect2.width, rect3.width)
Conditional Expressions:
strokeWidth <== when (hover) then 4 otherwise 0
Compound Expressions:
text <== when (rect.hover || circle.hover && !disabled) then
  textField.text + " is enabled" otherwise "disabled"

                                                               58
Animation in Scala
val timeline = new Timeline {
  cycleCount = INDEFINITE
  autoReverse = true
  keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
      circle.centerX -> random * stage.width,
      circle.centerY -> random * stage.height
    )
  }
}
timeline.play();

                                                          59
JavaFX Script-like animation
Animation in Scala      syntax: at (duration) {keyframes}
val timeline = new Timeline {
  cycleCount = INDEFINITE
  autoReverse = true
  keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
      circle.centerX -> random * stage.width,
      circle.centerY -> random * stage.height
    )
  }
}
timeline.play();

                                                            60
Animation in Scala
val timeline = new Timeline {
  cycleCount = INDEFINITE
  autoReverse = true
  keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
      circle.centerX -> random * stage.width,
      circle.centerY -> random * stage.height
    )
  }
}
                              Operator overloading for animation
timeline.play();
                                             syntax
                                                                   61
Animation in Scala
val timeline = new Timeline {
  cycleCount = INDEFINITE
  autoReverse = true
  keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
 circle.centerX -> random * stage.width tween EASE_BOTH,
 circle.centerY -> random * stage.height tween EASE_IN
    )
  }
}
timeline.play();            Optional tween
                              syntax
                                                           62
Event Listeners in Scala
>   Supported using the built-in Closure syntax
>   Arguments for event objects
>   100% type-safe


    onMouseClicked = { (e: MouseEvent) =>
      Timeline(at(3 s){radius->0}).play()
    }


                                                  63
Event Listeners in Scala
>   Supported using the built-in Closure syntax
>   Arguments for event objects
>   100% type-safe


    onMouseClicked = { (e: MouseEvent) =>
      Timeline(at(3 s){radius->0}).play()
    }
                       Compact syntax
                          {body}
                                                  64
Event Listeners in Scala
>   Supported using the built-in Closure syntax
>   Arguments for event objects
                                                  Event parameter
>   100% type-safe                                {(event) => body}


    onMouseClicked = { (e: MouseEvent) =>
      Timeline(at(3 s){radius->0}).play()
    }


                                                                      65
TableView in ScalaFX
def dateFormat = new SimpleDateFormat("yyyy-MM-dd")
new TableView[Speaker](persons) {
  columns = Seq(
   new TableColumn[Speaker, String] {
     text: "Name"
     converter = {_.firstName}
   } new TableColumn[Speaker, String] {
     text: "Age"
     converter = {_.age}
   } new TableColumn[Speaker, String] {
     text: "Gender"
     converter = {_.gender}
   } new TableColumn[Speaker, String] {
     text: "Birth"
     converter = {dateFormat.format(_.dob)},
   }
)}

                                                      66
JavaFX With Visage




                     67
About Project Visage
>   “Visage is a domain specific language (DSL) designed for the
    express purpose of writing user interfaces.”



>   Visage project goals:
       Compile to JavaFX Java APIs
       Evolve the Language (Annotations, Maps, etc.)
       Support Other Toolkits

>   Come join the team!
>   For more info: http://visage-lang.org/
                                                                   68
Java vs. Visage DSL
public class VanishingCircles extends Application {                                           var circles:Circle[];
                                                                                              Stage {
    public static void main(String[] args) {                                                    title: "Vanishing Circles"
      Application.launch(args);                                                                 Scene {
    }                                                                                             width: 800
                                                                                                  height: 600
    @Override                                                                                     fill: BLACK
    public void start(Stage primaryStage) {                                                       Group {
      primaryStage.setTitle("Vanishing Circles");                                                   circles = for (i in [1..50]) {
      Group root = new Group();                                                                       def c:Circle = Circle {
      Scene scene = new Scene(root, 800, 600, Color.BLACK);                                             centerX: random() * 800
      List<Circle> circles = new ArrayList<Circle>();                                                   centerY: random() * 600
      for (int i = 0; i < 50; i++) {                                                                    radius: 150
        final Circle circle = new Circle(150);                                                          fill: color(random(), random(), random(), .2)

                  40 Lines
        circle.setCenterX(Math.random() * 800);
        circle.setCenterY(Math.random() * 600);
        circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2));
        circle.setEffect(new BoxBlur(10, 10, 3));
                                                                                                               35 Lines
                                                                                                        effect: BoxBlur {
                                                                                                          height: 10
                                                                                                          width: 10
                                                                                                          iterations: 3


                  1299 Characters
        circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
          public void handle(MouseEvent t) {
            KeyValue collapse = new KeyValue(circle.radiusProperty(), 0);
            new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play();
                                                                                                        }
                                                                                                               487 Characters
                                                                                                        stroke: WHITE
                                                                                                        strokeWidth: bind if (c.hover) 5 else 0
                                                                                                        onMouseClicked: function(e) {
          }                                                                                               Timeline {at (3s) {c.radius => 0}}.play()
        });                                                                                             }
        circle.setStroke(Color.WHITE);                                                                }
        circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty())                     }
          .then(4)                                                                                }
          .otherwise(0));                                                                       }
        circles.add(circle);                                                                  }
      }
      root.getChildren().addAll(circles);                                                     Timeline {
      primaryStage.setScene(scene);                                                             for (circle in circles) at (40s) {
      primaryStage.show();                                                                        circle.centerX => random() * 800;
                                                                                                  circle.centerY => random() * 600
        Timeline moveCircles = new Timeline();                                                  }
        for (Circle circle : circles) {                                                       }.play()
          KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800);
          KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600);
          moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY));
        }
        moveCircles.play();
    }
}




                                                                                                                                                        69
How about JavaFX on… Visage
Stage {
  title: "Vanishing Circles"
  scene: Scene {
    width: 800
    height: 600
    fill: BLACK
    content: Group {
      circles = for (i in [1..50]) {
        Circle {
          centerX: random() * 800
          centerY: random() * 600
        }
      }
    }
  }
}

                                       70
How about JavaFX on… Visage
Stage {
  title: "Vanishing Circles"
  scene: Scene {
    width: 800
    height: 600
    fill: BLACK
    content: Group {
      circles = for (i in [1..50]) {
        Circle {
          centerX: random() * 800
          centerY: random() * 600
        }
      }
    }
  }
}

                                       71
How about JavaFX on… Visage
Stage {
  title: "Vanishing Circles"
  Scene {
    width: 800
    height: 600
    fill: BLACK
    Group {
      circles = for (i in [1..50]) {
        Circle {
          centerX: random() * 800
          centerY: random() * 600
        }
      }
    }
  }
}

                                       72
Visage is JavaFX Script++
>   Default Parameters
>   New Literal Syntax For:
       Angles – 35deg, 4rad, 1turn
       Colors – #DDCCBB, #AA33AA|CC
       Lengths – 5px, 2pt, 3in, 4sp
>   Null-check Dereference
       var width = rect.!width
>   Built-in Bindable Maps (coming soon!)
       var fruitMap = ["red" : apple, "yellow" : banana]
       var fruit = bind fruitMap["red"]
                                                            73
Visage and JavaFX 2.0 are made for each other…
>   Enhanced Binding
       Retains lazy evaluation properties with additional expressive power
>   Integrated Collections
       Sequences and Maps automatically convert between JavaFX
        Observable Lists/Maps
>   Built-in Animation Syntax
       Ties into JavaFX animation subsystem
       Provides consistent, clean APIs



                                                                              74
Other JVM Languages to Try
>   JRuby
       Faithful to Ruby language with the power of the JVM
>   Gosu
       Up and coming language created at GuideWire
       Easy to enhance libraries and create DSLs
>   Mirah
       Invented by Charles Nutter
       Local Type Inference, Static and Dynamic Typing
>   Fantom
       Created by Brian and Andy Frank
       Portable to Java and .NET
       Local Type Inference, Static and Dynamic Typing

                                                              75
Conclusion
>   You can write JavaFX applications in pure Java
>   JavaFX is also usable in alternate languages
>   You can get improved support using DSL libraries
       GroovyFX
       ScalaFX
>   Or a dedicated UI JVM Language
       Visage
Stephen Chin
                                                            stephen.chin@oracle.com
                                                            tweet: @steveonjava




Thanks to Dean Iverson and Jonathan Giles for help preparing this talk          77

Más contenido relacionado

La actualidad más candente

Java FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideJava FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideStephen Chin
 
JavaFX and Scala in the Cloud
JavaFX and Scala in the CloudJavaFX and Scala in the Cloud
JavaFX and Scala in the CloudStephen Chin
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84Mahmoud Samir Fayed
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Howard Lewis Ship
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeAijaz Ansari
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Ralph Schindler
 
The Ring programming language version 1.2 book - Part 79 of 84
The Ring programming language version 1.2 book - Part 79 of 84The Ring programming language version 1.2 book - Part 79 of 84
The Ring programming language version 1.2 book - Part 79 of 84Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84Mahmoud Samir Fayed
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldBTI360
 
On the Impossibility of Batch Update for Cryptographic Accumulators
On the Impossibility of Batch Update for Cryptographic AccumulatorsOn the Impossibility of Batch Update for Cryptographic Accumulators
On the Impossibility of Batch Update for Cryptographic AccumulatorsPhilippe Camacho, Ph.D.
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007Damien Seguy
 

La actualidad más candente (20)

Java FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideJava FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's Guide
 
JavaFX and Scala in the Cloud
JavaFX and Scala in the CloudJavaFX and Scala in the Cloud
JavaFX and Scala in the Cloud
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
The Ring programming language version 1.2 book - Part 79 of 84
The Ring programming language version 1.2 book - Part 79 of 84The Ring programming language version 1.2 book - Part 79 of 84
The Ring programming language version 1.2 book - Part 79 of 84
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
 
Php forum2015 tomas_final
Php forum2015 tomas_finalPhp forum2015 tomas_final
Php forum2015 tomas_final
 
The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
On the Impossibility of Batch Update for Cryptographic Accumulators
On the Impossibility of Batch Update for Cryptographic AccumulatorsOn the Impossibility of Batch Update for Cryptographic Accumulators
On the Impossibility of Batch Update for Cryptographic Accumulators
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
 
Xm lparsers
Xm lparsersXm lparsers
Xm lparsers
 

Destacado

Internet of Things Magic Show
Internet of Things Magic ShowInternet of Things Magic Show
Internet of Things Magic ShowStephen Chin
 
Confessions of a Former Agile Methodologist
Confessions of a Former Agile MethodologistConfessions of a Former Agile Methodologist
Confessions of a Former Agile MethodologistStephen Chin
 
Java on Raspberry Pi Lab
Java on Raspberry Pi LabJava on Raspberry Pi Lab
Java on Raspberry Pi LabStephen Chin
 
JCrete Embedded Java Workshop
JCrete Embedded Java WorkshopJCrete Embedded Java Workshop
JCrete Embedded Java WorkshopStephen Chin
 
Raspberry Pi with Java (JJUG)
Raspberry Pi with Java (JJUG)Raspberry Pi with Java (JJUG)
Raspberry Pi with Java (JJUG)Stephen Chin
 
Raspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXRaspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXStephen Chin
 
JavaFX GUI architecture with Clojure core.async
JavaFX GUI architecture with Clojure core.asyncJavaFX GUI architecture with Clojure core.async
JavaFX GUI architecture with Clojure core.asyncFalko Riemenschneider
 
Zombie Time - JSR 310 for the Undead
Zombie Time - JSR 310 for the UndeadZombie Time - JSR 310 for the Undead
Zombie Time - JSR 310 for the UndeadStephen Chin
 
Raspberry Pi Gaming 4 Kids - Dutch Version
Raspberry Pi Gaming 4 Kids - Dutch VersionRaspberry Pi Gaming 4 Kids - Dutch Version
Raspberry Pi Gaming 4 Kids - Dutch VersionStephen Chin
 
Raspberry pi gaming 4 kids
Raspberry pi gaming 4 kidsRaspberry pi gaming 4 kids
Raspberry pi gaming 4 kidsStephen Chin
 
RetroPi Handheld Raspberry Pi Gaming Console
RetroPi Handheld Raspberry Pi Gaming ConsoleRetroPi Handheld Raspberry Pi Gaming Console
RetroPi Handheld Raspberry Pi Gaming ConsoleStephen Chin
 
OpenJFX on Android and Devices
OpenJFX on Android and DevicesOpenJFX on Android and Devices
OpenJFX on Android and DevicesStephen Chin
 
JavaFX on Mobile (by Johan Vos)
JavaFX on Mobile (by Johan Vos)JavaFX on Mobile (by Johan Vos)
JavaFX on Mobile (by Johan Vos)Stephen Chin
 
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)Stephen Chin
 
Confessions of a Former Agile Methodologist (JFrog Edition)
Confessions of a Former Agile Methodologist (JFrog Edition)Confessions of a Former Agile Methodologist (JFrog Edition)
Confessions of a Former Agile Methodologist (JFrog Edition)Stephen Chin
 
Oracle IoT Kids Workshop
Oracle IoT Kids WorkshopOracle IoT Kids Workshop
Oracle IoT Kids WorkshopStephen Chin
 
Java 8 for Tablets, Pis, and Legos
Java 8 for Tablets, Pis, and LegosJava 8 for Tablets, Pis, and Legos
Java 8 for Tablets, Pis, and LegosStephen Chin
 
Devoxx4Kids NAO Workshop
Devoxx4Kids NAO WorkshopDevoxx4Kids NAO Workshop
Devoxx4Kids NAO WorkshopStephen Chin
 
Devoxx4Kids Lego Workshop
Devoxx4Kids Lego WorkshopDevoxx4Kids Lego Workshop
Devoxx4Kids Lego WorkshopStephen Chin
 

Destacado (20)

DukeScript
DukeScriptDukeScript
DukeScript
 
Internet of Things Magic Show
Internet of Things Magic ShowInternet of Things Magic Show
Internet of Things Magic Show
 
Confessions of a Former Agile Methodologist
Confessions of a Former Agile MethodologistConfessions of a Former Agile Methodologist
Confessions of a Former Agile Methodologist
 
Java on Raspberry Pi Lab
Java on Raspberry Pi LabJava on Raspberry Pi Lab
Java on Raspberry Pi Lab
 
JCrete Embedded Java Workshop
JCrete Embedded Java WorkshopJCrete Embedded Java Workshop
JCrete Embedded Java Workshop
 
Raspberry Pi with Java (JJUG)
Raspberry Pi with Java (JJUG)Raspberry Pi with Java (JJUG)
Raspberry Pi with Java (JJUG)
 
Raspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXRaspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFX
 
JavaFX GUI architecture with Clojure core.async
JavaFX GUI architecture with Clojure core.asyncJavaFX GUI architecture with Clojure core.async
JavaFX GUI architecture with Clojure core.async
 
Zombie Time - JSR 310 for the Undead
Zombie Time - JSR 310 for the UndeadZombie Time - JSR 310 for the Undead
Zombie Time - JSR 310 for the Undead
 
Raspberry Pi Gaming 4 Kids - Dutch Version
Raspberry Pi Gaming 4 Kids - Dutch VersionRaspberry Pi Gaming 4 Kids - Dutch Version
Raspberry Pi Gaming 4 Kids - Dutch Version
 
Raspberry pi gaming 4 kids
Raspberry pi gaming 4 kidsRaspberry pi gaming 4 kids
Raspberry pi gaming 4 kids
 
RetroPi Handheld Raspberry Pi Gaming Console
RetroPi Handheld Raspberry Pi Gaming ConsoleRetroPi Handheld Raspberry Pi Gaming Console
RetroPi Handheld Raspberry Pi Gaming Console
 
OpenJFX on Android and Devices
OpenJFX on Android and DevicesOpenJFX on Android and Devices
OpenJFX on Android and Devices
 
JavaFX on Mobile (by Johan Vos)
JavaFX on Mobile (by Johan Vos)JavaFX on Mobile (by Johan Vos)
JavaFX on Mobile (by Johan Vos)
 
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
 
Confessions of a Former Agile Methodologist (JFrog Edition)
Confessions of a Former Agile Methodologist (JFrog Edition)Confessions of a Former Agile Methodologist (JFrog Edition)
Confessions of a Former Agile Methodologist (JFrog Edition)
 
Oracle IoT Kids Workshop
Oracle IoT Kids WorkshopOracle IoT Kids Workshop
Oracle IoT Kids Workshop
 
Java 8 for Tablets, Pis, and Legos
Java 8 for Tablets, Pis, and LegosJava 8 for Tablets, Pis, and Legos
Java 8 for Tablets, Pis, and Legos
 
Devoxx4Kids NAO Workshop
Devoxx4Kids NAO WorkshopDevoxx4Kids NAO Workshop
Devoxx4Kids NAO Workshop
 
Devoxx4Kids Lego Workshop
Devoxx4Kids Lego WorkshopDevoxx4Kids Lego Workshop
Devoxx4Kids Lego Workshop
 

Similar a Hacking JavaFX with Groovy, Clojure, Scala, and Visage

JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)Stephen Chin
 
JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]Stephen Chin
 
JavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx VersionJavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx VersionStephen Chin
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesStephen Chin
 
Don't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFXDon't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFXAlain Béarez
 
JavaFX 2.0 and Alternative Languages
JavaFX 2.0 and Alternative LanguagesJavaFX 2.0 and Alternative Languages
JavaFX 2.0 and Alternative LanguagesStephen Chin
 
Painless Persistence with Realm
Painless Persistence with RealmPainless Persistence with Realm
Painless Persistence with RealmChristian Melchior
 
Greach, GroovyFx Workshop
Greach, GroovyFx WorkshopGreach, GroovyFx Workshop
Greach, GroovyFx WorkshopDierk König
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...Stephen Chin
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
Scala introduction
Scala introductionScala introduction
Scala introductionvito jeng
 
Building mobile web apps with Mobello
Building mobile web apps with MobelloBuilding mobile web apps with Mobello
Building mobile web apps with MobelloJeong-Geun Kim
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonAlex Payne
 

Similar a Hacking JavaFX with Groovy, Clojure, Scala, and Visage (20)

JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
 
JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]
 
JavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx VersionJavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx Version
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
 
Don't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFXDon't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFX
 
JavaFX 2.0 and Alternative Languages
JavaFX 2.0 and Alternative LanguagesJavaFX 2.0 and Alternative Languages
JavaFX 2.0 and Alternative Languages
 
Painless Persistence with Realm
Painless Persistence with RealmPainless Persistence with Realm
Painless Persistence with Realm
 
Greach, GroovyFx Workshop
Greach, GroovyFx WorkshopGreach, GroovyFx Workshop
Greach, GroovyFx Workshop
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
ES6(ES2015) is beautiful
ES6(ES2015) is beautifulES6(ES2015) is beautiful
ES6(ES2015) is beautiful
 
Building mobile web apps with Mobello
Building mobile web apps with MobelloBuilding mobile web apps with Mobello
Building mobile web apps with Mobello
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
SVGo workshop
SVGo workshopSVGo workshop
SVGo workshop
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 

Más de Stephen Chin

DevOps Tools for Java Developers v2
DevOps Tools for Java Developers v2DevOps Tools for Java Developers v2
DevOps Tools for Java Developers v2Stephen Chin
 
10 Ways Everyone Can Support the Java Community
10 Ways Everyone Can Support the Java Community10 Ways Everyone Can Support the Java Community
10 Ways Everyone Can Support the Java CommunityStephen Chin
 
Java Clients and JavaFX: The Definitive Guide
Java Clients and JavaFX: The Definitive GuideJava Clients and JavaFX: The Definitive Guide
Java Clients and JavaFX: The Definitive GuideStephen Chin
 
DevOps Tools for Java Developers
DevOps Tools for Java DevelopersDevOps Tools for Java Developers
DevOps Tools for Java DevelopersStephen Chin
 
Java Clients and JavaFX - Presented to LJC
Java Clients and JavaFX - Presented to LJCJava Clients and JavaFX - Presented to LJC
Java Clients and JavaFX - Presented to LJCStephen Chin
 
LUGOD Raspberry Pi Hacking
LUGOD Raspberry Pi HackingLUGOD Raspberry Pi Hacking
LUGOD Raspberry Pi HackingStephen Chin
 
Moving to the Client - JavaFX and HTML5
Moving to the Client - JavaFX and HTML5Moving to the Client - JavaFX and HTML5
Moving to the Client - JavaFX and HTML5Stephen Chin
 
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)Stephen Chin
 
JavaFX 2 Using the Spring Framework
JavaFX 2 Using the Spring FrameworkJavaFX 2 Using the Spring Framework
JavaFX 2 Using the Spring FrameworkStephen Chin
 

Más de Stephen Chin (9)

DevOps Tools for Java Developers v2
DevOps Tools for Java Developers v2DevOps Tools for Java Developers v2
DevOps Tools for Java Developers v2
 
10 Ways Everyone Can Support the Java Community
10 Ways Everyone Can Support the Java Community10 Ways Everyone Can Support the Java Community
10 Ways Everyone Can Support the Java Community
 
Java Clients and JavaFX: The Definitive Guide
Java Clients and JavaFX: The Definitive GuideJava Clients and JavaFX: The Definitive Guide
Java Clients and JavaFX: The Definitive Guide
 
DevOps Tools for Java Developers
DevOps Tools for Java DevelopersDevOps Tools for Java Developers
DevOps Tools for Java Developers
 
Java Clients and JavaFX - Presented to LJC
Java Clients and JavaFX - Presented to LJCJava Clients and JavaFX - Presented to LJC
Java Clients and JavaFX - Presented to LJC
 
LUGOD Raspberry Pi Hacking
LUGOD Raspberry Pi HackingLUGOD Raspberry Pi Hacking
LUGOD Raspberry Pi Hacking
 
Moving to the Client - JavaFX and HTML5
Moving to the Client - JavaFX and HTML5Moving to the Client - JavaFX and HTML5
Moving to the Client - JavaFX and HTML5
 
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)
JavaFX 2 - A Java Developer's Guide (San Antonio JUG Version)
 
JavaFX 2 Using the Spring Framework
JavaFX 2 Using the Spring FrameworkJavaFX 2 Using the Spring Framework
JavaFX 2 Using the Spring Framework
 

Último

Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?SANGHEE SHIN
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIUdaiappa Ramachandran
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.francesco barbera
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
GenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncGenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncObject Automation
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 

Último (20)

Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AI
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
GenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncGenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation Inc
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 

Hacking JavaFX with Groovy, Clojure, Scala, and Visage

  • 1. Hacking JavaFX with Groovy, Clojure, Scala, and Visage Stephen Chin Java Evangelist, Oracle stephen.chin@oracle.com tweet: @steveonjava
  • 2. Meet the Presenter Stephen Chin > Java Evangelist, Oracle > Author, Pro JavaFX Platform 2 Family Man > Open Source Hacker  JFXtras  ScalaFX Motorcyclist  Visage > User Group Co-Leader  Silicon Valley JavaFX User Group  Streamed Live!
  • 3. Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle.
  • 4. JavaFX 2.0 Platform Immersive Application Experience Leverage your Java skills with modern JavaFX APIs > Cross-platform Animation, Video, Charting > Integrate Java, JavaScript, and HTML5 in the same application > New graphics stack takes advantage of hardware acceleration for 2D and 3D applications > Use your favorite IDE: NetBeans, Eclipse, IntelliJ, etc.
  • 6. Programming Languages > JavaFX 2.0 APIs are now in Java  Pure Java APIs for all of JavaFX  Binding and Sequences exposed as Java APIs  FXML Markup for tooling > Embrace all JVM languages  Groovy, Scala, Clojure, JRuby  Fantom, Mira, Gosu, Jython, etc. > JavaFX Script is no longer supported by Oracle  Existing JavaFX Script based applications will continue to run  Visage is the open-source successor to the JavaFX Script language
  • 8. Vanishing Circles in Java public class VanishingCircles extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Vanishing Circles"); Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); List<Circle> circles = new ArrayList<Circle>(); for (int i = 0; i < 50; i++) { final Circle circle = new Circle(150); circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); 40 Lines circle.setEffect(new BoxBlur(10, 10, 3)); circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); 1299 Characters new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } }); circle.setStroke(Color.WHITE); circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) .then(4) .otherwise(0)); circles.add(circle); } root.getChildren().addAll(circles); primaryStage.setScene(scene); primaryStage.show(); Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 8
  • 9. Application Skeleton public class VanishingCircles extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Vanishing Circles"); Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); [create the circles…] root.getChildren().addAll(circles); primaryStage.setScene(scene); primaryStage.show(); [begin the animation…] } }
  • 10. Create the Circles List<Circle> circles = new ArrayList<Circle>(); for (int i = 0; i < 50; i++) { final Circle circle = new Circle(150); circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); circle.setStroke(Color.WHITE); [setup binding…] [setup event listeners…] circles.add(circle); } 10
  • 11. Setup Binding circle.strokeWidthProperty().bind(Bindings .when(circle.hoverProperty()) .then(4) .otherwise(0) ); 11
  • 12. Setup Event Listeners circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } }); 12
  • 13. Begin the Animation Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); 13
  • 15. Features of Groovy > Modern language  Closures  AST Transforms  Strongly typed dynamic language > Tight integration with Java  Very easy to port from Java to Groovy > Declarative syntax with GroovyFX Builders  Familiar to Groovy and JavaFX Script developers
  • 16. Java vs. GroovyFX DSL public class VanishingCircles extends Application { GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() public static void main(String[] args) { def rand = new Random().&nextInt Application.launch(args); def circles = [] } sg.stage(title: 'Vanishing Circles', show: true) { @Override scene(fill: black, width: 800, height: 600) { public void start(Stage primaryStage) { 50.times { primaryStage.setTitle("Vanishing Circles"); circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, Group root = new Group(); strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { Scene scene = new Scene(root, 800, 600, Color.BLACK); fill rgb(rand(255), rand(255), rand(255), 0.2) List<Circle> circles = new ArrayList<Circle>(); effect boxBlur(width: 10, height: 10, iterations: 3) for (int i = 0; i < 50; i++) { onMouseClicked { e -> 29 Lines final Circle circle = new Circle(150); timeline { 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); } } at(3.s) { change e.source.radiusProperty() to 0 } }.play() 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } 671 Characters timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) { } circles.each { circle -> }); at (40.s) { circle.setStroke(Color.WHITE); change circle.centerXProperty() to rand(800) circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) change circle.centerYProperty() to rand(600) .then(4) } .otherwise(0)); } circles.add(circle); }.play() } } root.getChildren().addAll(circles); } primaryStage.setScene(scene); primaryStage.show(); Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 16
  • 17. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] sg.stage(title: 'Vanishing Circles', show: true) { scene(fill: black, width: 800, height: 600) { 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 17
  • 18. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] Builder for GroovyFX scene graphs sg.stage(title: 'Vanishing Circles', show: true) { scene(fill: black, width: 800, height: 600) { 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 18
  • 19. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] sg.stage(title: 'Vanishing Circles', show: true) { scene(fill: black, width: 800, height: 600) { 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, Declarative Stage definition strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 19
  • 20. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] Inline property definitions sg.stage(title: 'Vanishing Circles', show: true) { scene(fill: black, width: 800, height: 600) { 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 20
  • 21. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] sg.stage(title: 'Vanishing Circles', show: true) { scene(fill: black, width: 800, height: 600) { Bind to properties 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 21
  • 22. GroovyFX.start { primaryStage -> def sg = new SceneGraphBuilder() def rand = new Random().&nextInt def circles = [] sg.stage(title: 'Vanishing Circles', show: Sequence Creation Via Loop true) { scene(fill: black, width: 800, height: 600) { 50.times { circles << circle(centerX: rand(800), centerY: rand(600), radius: 150, stroke: white, strokeWidth: bind('hover', converter: {val -> val ? 4 : 0})) { fill rgb(rand(255), rand(255), rand(255), 0.2) effect boxBlur(width: 10, height: 10, iterations: 3) } } } } } 22
  • 23. Animation in GroovyFX timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) { circles.each { circle -> at (40.s) { change circle.centerXProperty() to rand(800) change circle.centerYProperty() to rand(600) } } }.play() 23
  • 24. Animation in GroovyFX timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) { circles.each { circle -> at (40.s) { change circle.centerXProperty() to rand(800) change circle.centerYProperty() to rand(600) } } Easy animation syntax: }.play() at (duration) {keyframes} 24
  • 25. Animation in GroovyFX timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) { circles.each { circle -> at (40.s) { change circle.centerXProperty() to rand(800) change circle.centerYProperty() to rand(600) } } }.play() Key frame DSL 25
  • 26. Animation in GroovyFX timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) { circles.each { circle -> at (40.s) { change circle.centerXProperty() to rand(800) tween ease_both change circle.centerYProperty() to rand(600) tween linear } } }.play() Optional easing 26
  • 27. Event Listeners in GroovyFX > Supported using the built-in Closure syntax > Optional arguments for event objects onMouseClicked { e -> timeline { at(3.s) { change e.source.radiusProperty() to 0 } }.play() } 27
  • 28. Event Listeners in GroovyFX > Supported using the built-in Closure syntax > Optional arguments for event objects onMouseClicked { MouseEvent e -> timeline { at(3.s) { change e.source.radiusProperty() to 0 } }.play() } Compact syntax {body} 28
  • 29. Event Listeners in GroovyFX > Supported using the built-in Closure syntax > Optional arguments for event objects Optional event parameter {event -> body} onMouseClicked { MouseEvent e -> timeline { at(3.s) { change e.source.radiusProperty() to 0 } }.play() } 29
  • 30. But wait, there is more Grooviness… 30
  • 31. Properties in Java public class Person { private StringProperty firstName; public void setFirstName(String val) { firstNameProperty().set(val); } public String getFirstName() { return firstNameProperty().get(); } public StringProperty firstNameProperty() { if (firstName == null) firstName = new SimpleStringProperty(this, "firstName"); return firstName; } private StringProperty lastName; public void setLastName(String value) { lastNameProperty().set(value); } public String getLastName() { return lastNameProperty().get(); } public StringProperty lastNameProperty() { if (lastName == null) // etc. } } 31
  • 32. Properties in GroovyFX public class Person { @FXBindable String firstName; @FXBindable String lastName; } 32
  • 33. Properties in GroovyFX public class Person { @FXBindable String firstName; @FXBindable String lastName = “Smith”; } Optional initializers 33
  • 34. TableView in Java ObservableList<Person> items = ... TableView<Person> tableView = new TableView<Person>(items); TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name"); firstNameCol.setCellValueFactory( new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() { public ObservableValue<String> call(CellDataFeatures<Person, String> p) { return p.getValue().firstNameProperty(); } }); tableView.getColumns().add(firstNameCol); 34
  • 35. TableView in GroovyFX def dateFormat = new SimpleDateFormat("yyyy-MM-dd"); tableView(items: persons) { tableColumn(property: "name", text: "Name", prefWidth: 150) tableColumn(property: "age", text: "Age", prefWidth: 50) tableColumn(property: "gender", text: "Gender", prefWidth: 150) tableColumn(property: "dob", text: "Birth", prefWidth: 150, type: Date, converter: { from -> return dateFormat.format(from) }) } 35
  • 36. Layout in Java TextField urlField = new TextField(“http://www.google.com”); HBox.setHgrow(urlField, Priority.ALWAYS); HBox hbox = new HBox(); hbox.getChildren().add(urlField); WebView webView = new WebView(); VBox.setVgrow(webView, Priority.ALWAYS); VBox vbox = new VBox(); vbox.getChildren().addAll(hbox, webView); 36
  • 37. Layout in GroovyFX sg.stage(title: "GroovyFX WebView Demo", show: true) { scene(fill: groovyblue, width: 1024, height: 800) { vbox { hbox(padding: 10, spacing: 5) { textField(“http://www.yahoo.com”, hgrow: "always") button("Go”) } webView(vgrow: "always") } } } 37
  • 39. Layout in GroovyFX gridPane(hgap: 5, vgap: 10, padding: 25) { columnConstraints(minWidth: 50, halignment: "right") columnConstraints(prefWidth: 250) label("Send Us Your Feedback", font: "24pt sanserif", row: 0, columnSpan: GridPane.REMAINING, halignment: "center", margin: [0, 0, 10]) label("Name: ", row: 1, column: 0) textField(promptText: "Your name", row: 1, column: 1, hgrow: 'always') label("Email:", row: 2, column: 0) textField(promptText: "Your email", row: 2, column: 1, hgrow: 'always') label("Message:", row: 3, column: 0, valignment: "baseline") textArea(row: 3, column: 1, hgrow: "always", vgrow: "always") button("Send Message", row: 4, column: 1, halignment: "right") } 39
  • 42. JavaFX With Clojure Artwork by Augusto Sellhorn http://sellmic.com/ 42
  • 43. A Little About Clojure > Started in 2007 by Rich Hickey > Functional Programming Language > Derived from LISP > Optimized for High Concurrency (def hello (fn [] "Hello world")) (hello) > … and looks nothing like Java! 43
  • 44. Clojure Syntax in One Slide Symbols Collections (commas optional) > numbers – 2.178 > Lists > ratios – 355/113 (1, 2, 3, 4, 5) > strings – “clojure”, “rocks” > Vectors > characters – a b c d [1, 2, 3, 4, 5] > symbols – a b c d > Maps > keywords – :alpha :beta {:a 1, :b 2, :c 3, :d 4} > boolean – true, false > Sets > null - nil #{:a :b :c :d :e} (plus macros that are syntactic sugar wrapping the above) 44
  • 45. Clojure GUI Example (defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true))) (javafxapp) 45
  • 46. Refined Clojure GUI Example (defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) (.setHeight 450) (.setScene (doto (Scene.) (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true))) (javafxapp) 46
  • 47. Refined Clojure GUI Example (defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) Doto allows nested data (.setHeight 450) (.setScene (doto (Scene.) structures (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true))) (javafxapp) 47
  • 48. Closures in Clojure > Inner classes can be created using proxy (.addListener hoverProperty (proxy [ChangeListener] [] (handle [p, o, v] (.setFill rect (if (.isHover rect) Color/GREEN Color/RED))))) 48
  • 49. Closures in Clojure > Inner classes can be created using proxy Proxy form: (proxy [class] [args] fs+) f => (name [params*] body) (.addListener hoverProperty (proxy [ChangeListener] [] (handle [p, o, v] (.setFill rect (if (.isHover rect) Color/GREEN Color/RED))))) 49
  • 51. What is Scala 2001 2006 • Scala Started • Scala v2.0 2003/2004 2011 • Scala v1.0 • Scala 2.9.2 (latest) > Started in 2001 by Martin Odersky > Compiles to Java bytecodes > Pure object-oriented language > Also a functional programming language 51
  • 52. Java vs. Scala DSL public class VanishingCircles extends Application { object VanishingCircles extends JFXApp { var circles: Seq[Circle] = null public static void main(String[] args) { stage = new Stage { Application.launch(args); title = "Vanishing Circles" } width = 800 height = 600 @Override scene = new Scene { public void start(Stage primaryStage) { fill = BLACK primaryStage.setTitle("Vanishing Circles"); circles = for (i <- 0 until 50) yield new Circle { Group root = new Group(); centerX = random * 800 Scene scene = new Scene(root, 800, 600, Color.BLACK); centerY = random * 600 List<Circle> circles = new ArrayList<Circle>(); radius = 150 for (int i = 0; i < 50; i++) { fill = color(random, random, random, .2) final Circle circle = new Circle(150); effect = new BoxBlur(10, 10, 3) 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); 33 Lines strokeWidth <== when (hover) then 4 otherwise 0 stroke = WHITE onMouseClicked = { Timeline(at (3 s) {radius -> 0}).play() 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } } 591 Characters content = circles } } }); circle.setStroke(Color.WHITE); new Timeline { circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) cycleCount = INDEFINITE .then(4) autoReverse = true .otherwise(0)); keyFrames = for (circle <- circles) yield at (40 s) { circles.add(circle); Set( } circle.centerX -> random * stage.width, root.getChildren().addAll(circles); circle.centerY -> random * stage.height primaryStage.setScene(scene); ) primaryStage.show(); } }.play(); Timeline moveCircles = new Timeline(); } for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 52
  • 53. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 scene = new Scene { fill = BLACK children = for (i <- 0 until 50) yield new Circle { centerX = random * 800 centerY = random * 600 radius = 150 fill = color(random, random, random, 0.2) effect = new BoxBlur(10, 10, 3) } } } } 53
  • 54. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height Base class for JavaFX applications = 600 scene = new Scene { fill = BLACK children = for (i <- 0 until 50) yield new Circle { centerX = random * 800 centerY = random * 600 radius = 150 fill = color(random, random, random, 0.2) effect = new BoxBlur(10, 10, 3) } } } } 54
  • 55. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 scene = new Scene { Declarative Stage definition fill = BLACK children = for (i <- 0 until 50) yield new Circle { centerX = random * 800 centerY = random * 600 radius = 150 fill = color(random, random, random, 0.2) effect = new BoxBlur(10, 10, 3) } } } } 55
  • 56. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Inline property definitions height = 600 scene = new Scene { fill = BLACK children = for (i <- 0 until 50) yield new Circle { centerX = random * 800 centerY = random * 600 radius = 150 fill = color(random, random, random, 0.2) effect = new BoxBlur(10, 10, 3) } } } } 56
  • 57. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 Sequence Creation Via Loop scene = new Scene { fill = BLACK children = for (i <- 0 until 50) yield new Circle { centerX = random * 800 centerY = random * 600 radius = 150 fill = color(random, random, random, 0.2) effect = new BoxBlur(10, 10, 3) } } } } 57
  • 58. Binding in Scala Infix Addition/Subtraction/Multiplication/Division: height <== rect1.height + rect2.height Aggregate Operators: width <== max(rect1.width, rect2.width, rect3.width) Conditional Expressions: strokeWidth <== when (hover) then 4 otherwise 0 Compound Expressions: text <== when (rect.hover || circle.hover && !disabled) then textField.text + " is enabled" otherwise "disabled" 58
  • 59. Animation in Scala val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width, circle.centerY -> random * stage.height ) } } timeline.play(); 59
  • 60. JavaFX Script-like animation Animation in Scala syntax: at (duration) {keyframes} val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width, circle.centerY -> random * stage.height ) } } timeline.play(); 60
  • 61. Animation in Scala val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width, circle.centerY -> random * stage.height ) } } Operator overloading for animation timeline.play(); syntax 61
  • 62. Animation in Scala val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width tween EASE_BOTH, circle.centerY -> random * stage.height tween EASE_IN ) } } timeline.play(); Optional tween syntax 62
  • 63. Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects > 100% type-safe onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 63
  • 64. Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects > 100% type-safe onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } Compact syntax {body} 64
  • 65. Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects Event parameter > 100% type-safe {(event) => body} onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 65
  • 66. TableView in ScalaFX def dateFormat = new SimpleDateFormat("yyyy-MM-dd") new TableView[Speaker](persons) { columns = Seq( new TableColumn[Speaker, String] { text: "Name" converter = {_.firstName} } new TableColumn[Speaker, String] { text: "Age" converter = {_.age} } new TableColumn[Speaker, String] { text: "Gender" converter = {_.gender} } new TableColumn[Speaker, String] { text: "Birth" converter = {dateFormat.format(_.dob)}, } )} 66
  • 68. About Project Visage > “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.” > Visage project goals:  Compile to JavaFX Java APIs  Evolve the Language (Annotations, Maps, etc.)  Support Other Toolkits > Come join the team! > For more info: http://visage-lang.org/ 68
  • 69. Java vs. Visage DSL public class VanishingCircles extends Application { var circles:Circle[]; Stage { public static void main(String[] args) { title: "Vanishing Circles" Application.launch(args); Scene { } width: 800 height: 600 @Override fill: BLACK public void start(Stage primaryStage) { Group { primaryStage.setTitle("Vanishing Circles"); circles = for (i in [1..50]) { Group root = new Group(); def c:Circle = Circle { Scene scene = new Scene(root, 800, 600, Color.BLACK); centerX: random() * 800 List<Circle> circles = new ArrayList<Circle>(); centerY: random() * 600 for (int i = 0; i < 50; i++) { radius: 150 final Circle circle = new Circle(150); fill: color(random(), random(), random(), .2) 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); 35 Lines effect: BoxBlur { height: 10 width: 10 iterations: 3 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } 487 Characters stroke: WHITE strokeWidth: bind if (c.hover) 5 else 0 onMouseClicked: function(e) { } Timeline {at (3s) {c.radius => 0}}.play() }); } circle.setStroke(Color.WHITE); } circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) } .then(4) } .otherwise(0)); } circles.add(circle); } } root.getChildren().addAll(circles); Timeline { primaryStage.setScene(scene); for (circle in circles) at (40s) { primaryStage.show(); circle.centerX => random() * 800; circle.centerY => random() * 600 Timeline moveCircles = new Timeline(); } for (Circle circle : circles) { }.play() KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 69
  • 70. How about JavaFX on… Visage Stage { title: "Vanishing Circles" scene: Scene { width: 800 height: 600 fill: BLACK content: Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } } } 70
  • 71. How about JavaFX on… Visage Stage { title: "Vanishing Circles" scene: Scene { width: 800 height: 600 fill: BLACK content: Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } } } 71
  • 72. How about JavaFX on… Visage Stage { title: "Vanishing Circles" Scene { width: 800 height: 600 fill: BLACK Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } } } 72
  • 73. Visage is JavaFX Script++ > Default Parameters > New Literal Syntax For:  Angles – 35deg, 4rad, 1turn  Colors – #DDCCBB, #AA33AA|CC  Lengths – 5px, 2pt, 3in, 4sp > Null-check Dereference  var width = rect.!width > Built-in Bindable Maps (coming soon!)  var fruitMap = ["red" : apple, "yellow" : banana]  var fruit = bind fruitMap["red"] 73
  • 74. Visage and JavaFX 2.0 are made for each other… > Enhanced Binding  Retains lazy evaluation properties with additional expressive power > Integrated Collections  Sequences and Maps automatically convert between JavaFX Observable Lists/Maps > Built-in Animation Syntax  Ties into JavaFX animation subsystem  Provides consistent, clean APIs 74
  • 75. Other JVM Languages to Try > JRuby  Faithful to Ruby language with the power of the JVM > Gosu  Up and coming language created at GuideWire  Easy to enhance libraries and create DSLs > Mirah  Invented by Charles Nutter  Local Type Inference, Static and Dynamic Typing > Fantom  Created by Brian and Andy Frank  Portable to Java and .NET  Local Type Inference, Static and Dynamic Typing 75
  • 76. Conclusion > You can write JavaFX applications in pure Java > JavaFX is also usable in alternate languages > You can get improved support using DSL libraries  GroovyFX  ScalaFX > Or a dedicated UI JVM Language  Visage
  • 77. Stephen Chin stephen.chin@oracle.com tweet: @steveonjava Thanks to Dean Iverson and Jonathan Giles for help preparing this talk 77

Notas del editor

  1. Stage.add??
  2. Stage.add??