JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)

on

  • 35,872 views

JavaFX 2.0 is the next version of a revolutionary rich client platform for developing immersive desktop applications. One of the new features in JavaFX 2.0 is a set of pure Java APIs that can be used ...

JavaFX 2.0 is the next version of a revolutionary rich client platform for developing immersive desktop applications. One of the new features in JavaFX 2.0 is a set of pure Java APIs that can be used from any JVM language, opening up tremendous possibilities. This presentation demonstrates the benefits of using JavaFX 2.0 together with the Scala programming language to provide a type-safe declarative syntax with support for lazy bindings and collections. Advanced language features, such as DelayedInit and @specialized will be discussed, as will ways of forcing prioritization of implicit conversions for n-level cases. Those who survive the pure technical geekiness of this talk will be rewarded with plenty of JavaFX UI eye candy.

Statistics

Views

Total Views
35,872
Views on SlideShare
3,748
Embed Views
32,124

Actions

Likes
3
Downloads
82
Comments
0

19 Embeds 32,124

http://code-opensocial.googleusercontent.com 23877
http://www.scalafx.org 4421
https://code-opensocial.googleusercontent.com 2871
http://www.developpez.net 789
http://scalafx.github.io 65
http://192.168.0.198 52
http://localhost 12
http://131.253.14.125 12
http://translate.googleusercontent.com 6
https://twitter.com 4
http://65.55.108.4 4
http://a0.twimg.com 2
https://www.linkedin.com 2
https://si0.twimg.com 2
http://nighthacking.com 1
http://paper.li 1
https://twimg0-a.akamaihd.net 1
http://us-w1.rockmelt.com 1
http://www.google.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Stage.add??

JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees) Presentation Transcript

  • 1. JavaFX 2.0 and Scala, Like Milkand Cookies Stephen Chin Chief Agile Methodologist, GXS steveonjava@gmail.com tweet: @steveonjava
  • 2. Meet the Presenter Stephen Chin > Chief Agile Methodologist, GXS Family Man > Java Champion > Open Source Hacker  JFXtras Motorcyclist  ScalaFX  Visage > User Group Leader  Silicon Valley JavaFX User Group  Streamed Live!
  • 3. JavaFX 2.0 PlatformImmersive Application Experience> 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.
  • 4. Programming Languages> 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> 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
  • 5. JavaFXScala 5
  • 6. JavaFX With Java
  • 7. JavaFX in Java> JavaFX API uses an enhanced JavaBeans pattern> Similar in feel to other UI toolkits (Swing, Pivot, etc.)> Uses builder pattern to minimize boilerplate
  • 8. Example Applicationpublic class HelloStage extends Application { @Override public void start(Stage stage) { stage.setTitle("Hello Stage"); stage.setWidth(600); stage.setHeight(450); Group root = new Group(); Scene scene = new Scene(root); scene.setFill(Color.LIGHTGREEN); stage.setScene(scene); stage.show(); } public static void main(String[] args) { Application.launch(args); }}
  • 9. Example Application Using Builderspublic class HelloStage extends Application { @Override public void start(Stage stage) { stage.setTitle("Hello Stage"); stage.setScene(SceneBuilder.create() .fill(Color.LIGHTGREEN) .width(600) .height(450) .build()); stage.show(); } public static void main(String[] args) { Application.launch(args); }}
  • 10. Observable Properties> Supports watching for changes to properties> Implemented via anonymous inner classes> Will take advantage of closures in the future
  • 11. Observable Pseudo-Propertiesfinal Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);rect.hoverProperty().addListener(new ChangeListener<Boolean>() {});
  • 12. Observable Pseudo-Propertiesfinal Rectangle rect = new Rectangle();rect.setX(40); The property we want to watchrect.setY(40);rect.setWidth(100);rect.setHeight(200);rect.hoverProperty().addListener(new ChangeListener<Boolean>() {});
  • 13. Observable Pseudo-Propertiesfinal Rectangle rect = new Rectangle();rect.setX(40); Only one listener used withrect.setY(40); generics to specify the data typerect.setWidth(100);rect.setHeight(200);rect.hoverProperty().addListener(new ChangeListener<Boolean>() {});
  • 14. Observable Pseudo-Propertiesfinal Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);rect.hoverProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean value) { }}); Refers to the Rectangle.hoverProperty()
  • 15. Observable Pseudo-Propertiesfinal Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);rect.hoverProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean value) { rect.setFill(rect.isHover() ? Color.GREEN : Color.RED); }});
  • 16. Binding> Unquestionably the biggest JavaFX Script innovation> Supported via a PropertyBinding class> Lazy invocation for high performance> Static construction syntax for simple cases  e.g.: bind(<property>), bindBiDirectional(<property>)
  • 17. Sequences in Java> Replaced with an Observable List> Public API is based on JavaFX sequences> Internal code can use lighter collections API> JavaFX 2.0 also has an Observable Map
  • 18. Vanishing Circles 18
  • 19. Application Skeletonpublic 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…] }}
  • 20. Create the CirclesList<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);} 20
  • 21. Setup Bindingcircle.strokeWidthProperty().bind(Bindings .when(circle.hoverProperty()) .then(4) .otherwise(0)); 21
  • 22. Setup Event Listenerscircle.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(); }}); 22
  • 23. Begin the AnimationTimeline 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(); 23
  • 24. JavaFX With Scala 24
  • 25. What is Scala 2012 2001 2006 • Scala 2.9.1-1 • Scala Started • Scala v2.0 (latest) 2003/2004 2011 • Scala v1.0 • Scala 2.9.1> Started in 2001 by Martin Odersky> Compiles to Java bytecodes> Pure object-oriented language> Also a functional programming language 25
  • 26. Why Scala?> Shares many language features with JavaFX Script that make GUI programming easier:  Static Type Checking – Catch your errors at compile time  Closures – Wrap behavior and pass it by reference  Declarative – Express the UI by describing what it should look like> Scala also supports Type Safe DSLs!  Implicit Conversions – type safe class extension  Operator Overloading – with standard precedence rules 26
  • 27. Java vs. Scala DSLpublic 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); } } } 591 Characters content = circles new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } }); new Timeline { circle.setStroke(Color.WHITE); cycleCount = INDEFINITE circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) autoReverse = true .then(4) keyFrames = for (circle <- circles) yield at (40 s) { .otherwise(0)); Set( circles.add(circle); circle.centerX -> random * stage.width, } circle.centerY -> random * stage.height root.getChildren().addAll(circles); ) 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(); }} 27
  • 28. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 scene = new Scene { fill = BLACK content = 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) } } }} 28
  • 29. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 class for JavaFX Base applications scene = new Scene { fill = BLACK content = 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) } } }} 29
  • 30. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 Declarative Stage scene = new Scene { fill = BLACK definition content = 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) } } }} 30
  • 31. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Inline property height = 600 definitions scene = new Scene { fill = BLACK content = 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) } } }} 31
  • 32. object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Sequence Creation Via height = 600 Loop scene = new Scene { fill = BLACK content = 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) } } }} 32
  • 33. Binding in ScalaInfix Addition/Subtraction/Multiplication/Division:height <== rect1.height + rect2.heightAggregate Operators:width <== max(rect1.width, rect2.width, rect3.width)Conditional Expressions:strokeWidth <== when (hover) then 4 otherwise 0Compound Expressions:text <== when (rect.hover || circle.hover && !disabled) then textField.text + " is enabled" otherwise "disabled" 33
  • 34. Animation in Scalaval 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(); 34
  • 35. JavaFX Script-like animationAnimation 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(); 35
  • 36. Animation in Scalaval 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(); Operator overloading for animation syntax 36
  • 37. Animation in Scalaval 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 37
  • 38. Event Listeners in Scala> Supported using the built-in Closure syntax> Optional arguments for event objects> 100% type-safe onMouseClicked = { Timeline(at(3 s){radius->0}).play() } 38
  • 39. Event Listeners in Scala> Supported using the built-in Closure syntax> Optional arguments for event objects> 100% type-safe onMouseClicked = { Timeline(at(3 s){radius->0}).play() } Compact syntax {body} 39
  • 40. Event Listeners in Scala> Supported using the built-in Closure syntax> Optional arguments for event objects Optional event> 100% type-safe parameter {(event) => body} onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 40
  • 41. ScalaFX Internals a.k.a. How to Write Your Own Scala DSLWith quotes from Stephen Colebourne (@jodastephen) to helpus keep our sanity!Disclaimer: Statements taken from http://blog.joda.org and may not accurately reflect his opinion or viewpoint. 41
  • 42. Application Initialization> JavaFX Requires all UI code executed on the Application Thread> But our ScalaFX Application has no start method:object VanishingCircles extends JFXApp { stage = new Stage { … }} How Does This Code Work?!? 42
  • 43. DelayedInit> Introduced in Scala 2.9> How to Use It:1. Extend a special trait called DelayedInit2. Implement a method of type:  def delayedInit(x: => Unit): Unit3. Store off the init closure and call it on the Application Thread Joda says… For me, Scala didnt throw enough away and added too much - a lethal combination. 43
  • 44. Hierarchical Implicit Conversions> ScalaFX defines a set of proxies that mirror the JavaFX hierarchy> JavaFX classes are "implicitly" wrapped when you call a ScalaFX API> But Scala implicit priority ignores type hierarchy! JFXNode SFXNode JFXShape ? SFXShape JFXCircle ! SFXCircle 44
  • 45. N-Level Implicit Precedence> Scala throws an exception if two implicits have the same precedence> Classes that are extended have 1 lower precedence:object HighPriorityIncludes extends LowerPriorityIncludes {…}trait LowerPriorityIncludes {…}> You can stack extended traits n-levels deep to reduce precision by n Joda says… Well, it may be type safe, but its also silent and very deadly. 45
  • 46. Properties> JavaFX supports properties of type Boolean, Integer, Long, Float, Double, String, and Object> Properties use Generics for type safety> But generics dont support primitives…> JavaFX solves this with 20 interfaces and 44 classes for all the type/readable/writable combinations.> Can we do better? 46
  • 47. @specialized> Special annotation that generates primitive variants of the class> Improves performance by avoiding boxing/unboxing trait ObservableValue[@specialized(Int, Long, Float , Double, Boolean) T, J]> Cuts down on code duplication (ScalaFX only has 18 property/value classes total) Joda says… Whatever the problem, the type system is bound to be part of the solution. 47
  • 48. Bindings> How does Scala know what order to evaluate this in?text <== when (rect.hover || circle.hover&& !disabled) then textField.text + " isenabled" otherwise "disabled And why the funky bind operator?!? 48
  • 49. Operator Precedence Rules> First Character Determines Precedence Lowest Precedence 10. (all letters) Exception Assignment 9. | Operators, which are 8. ^ even lower… 7. & 6. < > 11. Assignment Operators 5. = ! end with equal 4. : > But dont start with equal 3. + * > And cannot be one of:  <= 2. / %  >= 1. (all other special  != characters) Highest Precedence 49
  • 50. Operator Precedencetext <== when (rect.hover || circle.hover 11 10 9&& !disabled) then textField.text + " is7 5 10 3enabled" otherwise "disabled" 10 Joda says… Personally, I find the goal of the open and flexible syntax (arbitrary DSLs) to be not worth the pain 50
  • 51. Conclusion> You can use Scala and JavaFX together.> ScalaFX provides cleaner APIs that are tailor designed for Scala.> Try using ScalaFX today and help contribute APIs for our upcoming 1.0 release! http://code.google.com/p/scalafx/
  • 52. Stephen Chin steveonjava@gmail.com tweet: @steveonjavaPro JavaFX 2 Platform Available Now! 52