Java FX 2.0 - A Developer's Guide

Preview:

DESCRIPTION

A University talk about JavaFX 2.0 do

Citation preview

JavaFX 2.0 – A Java Developer's Guide

Stephen Chin Chief Agile Methodologist, GXS http://steveonjava.com @steveonjava

Peter Pilgrim Oracle Java Champion http://www.xenonique.co.uk/blog/ @peter_pilgrim

Meet the Presenters

Stephen Chin @steveonjava

Motorcyclist

Family Man

Peter Pilgrim @peter_pilgrim

Football, Music & Partner

This is a Participatory Session!

>  Every now and then we will say something interesting… and it will go out in a tweet.

>  Follow @steveonjava to watch the tweets and retweet the ones you like to your followers

>  Feel free to create your own tweets using the hash tags "#JavaFX #Devoxx"

>  We have some goodies for folks who play. J

3

http://blogs.oracle.com/chrisoliver/entry/epitaph 4

At the end of the day, on the one hand we have computer systems, and on the other, people. Connecting them together, and allowing people to interact with computer systems in a compelling way, requires graphical user interfaces

Chris Oliver, Creator of F3

JavaFX 2.0 Platform

Immersive Desktop Experience Combining the Best of JavaFX and Web Technologies >  Leverage your Java skills with modern

JavaFX APIs

>  Integrate Java, JavaScript, and HTML5 in the same application

>  New graphics stack takes advantage of hardware acceleration for 2D and 3D applications

>  Integrate in Swing applications using JFXPanel

>  User your favorite IDE: NetBeans, Eclipse, IntelliJ, etc.

Demo Video Fracture

Headline News

>  RT @Stephan007: The #JavaOne11 channel on #Parleys passed 51.800 views! Most viewed: "Introduction to #JavaFX 2.0", close to 11,000 - @JavaFX4You, 9th November 2011

>  The most interesting announcement came when Oracle demoed both Java and JavaFX applications running on a Windows tablet, an iPad, and a "Linux-based tablet". - Eric Bruno, Dr Dobbs Journal, 5th October 2011

7

Platform Support

>  Windows fully supported l  For 3D you need one of the supported graphics

cards (ATI, NVidia, Intel) >  Mac OS X preview available >  Linux Planned for end of 2012

8

Windows OS Requirements

Operating System (32-Bit and 64-Bit) Browsers (32-Bit and 64-Bit) Windows XP Home and Professional with Service Pack 3

Internet Explorer 7 and 8 Chrome

Windows Vista Home Basic, Home Premium, Business, and Ultimate with Service Pack 2

Internet Explorer 7, 8, and 9 Firefox 3.5, 3.6, and 4 Chrome

Windows 7 Home Premium, Professional, and Ultimate

Internet Explorer 8 and 9 Firefox 3.5, 3.6, and 4 Chrome

9

Supported Graphics Cards

Graphics Card Supported Graphics Processing Units (GPUs)

NVIDIA Mobile GPUs: GeForce 8M and 100M series or higher, NVS 2100M series or higher, and Mobility Quadro FX 300M series or higher Desktop GPUs: GeForce 8 and 100 series or higher Workstation GPUs: Quadro FX 300 series or higher

ATI Mobile GPUs: Mobility Radeon HD 3000, 4000, and 5000 series Desktop GPUs: Radeon HD 2400, 3000, 4000, 5000, and 6000 series

Intel Mobile GPUs: GMA 4500MHD and GMA HD Desktop GPUs: GMA 4500 and GMA HD

10

Building JavaFX Applications

>  Deploys in the browser or on desktop >  Pure Java APIs >  Includes builders for declarative construction >  Alternative languages can also be used for

simpler UI creation l  GroovyFX l  ScalaFX l  Visage

11

Hello Devoxx (Java Version)

public  class  HelloDevoxx  extends  Application  {      public  static  void  main(String[]  args)  {          launch(args);      }      @Override      public  void  start(Stage  primaryStage)  {          primaryStage.setTitle("Hello  Devoxx");          Group  root  =  new  Group();          Scene  scene  =  new  Scene(root,  400,  250,  Color.ALICEBLUE);          Text  text  =  new  Text();          text.setX(105);          text.setY(120);          text.setFont(new  Font(30));          text.setText("Hello  Devoxx");          root.getChildren().add(text);                          primaryStage.setScene(scene);          primaryStage.show();      }  }  

12

19 Lines 425 Characters

Hello Devoxx (Builder Version)

public  void  start(Stage  primaryStage)  {      primaryStage.setTitle("Hello  Devoxx");      primaryStage.setScene(SceneBuilder.create()          .width(400)          .height(250)          .fill(Color.ALICEBLUE)          .root(              GroupBuilder.create().children(              TextBuilder.create()                  .x(105)                  .y(120)                  .text("Hello  Devoxx")                  .font(new  Font(30))                  .build()              ).build()          )      .build());      primaryStage.show();  }  

13

25 Lines 418 Characters

Hello Devoxx (GroovyFX Version)

GroovyFX.start  {  primaryStage  -­‐>      def  sg  =  new  SceneGraphBuilder()      sg.stage(          title:  'Hello  Devoxx',          show:  true)  {              scene(                  fill:  aliceblue,                  width:  400,                  height:  250)  {                      text(                          x:  105,                          y:  120,                          text:  "Hello  Devoxx"                          font:  "30pt")                  }          }  }  

14

17 Lines 190 Characters

Hello Devoxx (ScalaFX Version)

object  HelloDevoxx  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Hello  Devoxx"          width  =  400          height  =  250          scene  =  new  Scene  {              fill  =  BLUE              Text  {                  x  =  105                  y  =  120                  text  =  "Hello  Devoxx"                  font  =  Font(size:  30)              }          }      }  }  

15

16 Lines 163 Characters

Hello Devoxx (Visage Version)

Stage  {      title:  "Hello  Devoxx"      width:  400      height:  250      scene:  Scene  {          fill:  BLUE          content:  Text  {              x:  105              y:  120              text:  "Hello  Devoxx"              font:  Font  {size:  30pt}          }      }  }  

16

14 Lines 129 Characters

Architecture of JavaFX 2.0

Java Virtual Machine

Java2D Open GL D3D

Prism Glass WinTk

Media Engine

Web Engine

JavaFX Public API

Quantum Toolkit

Properties, Lists, Binding 18

JavaFX 2.0 Fundamentals

JavaFX 2.0 Properties

>  Primitive Properties >  Object Properties >  FX List Collection Properties

>  Properties are:

l  Observable l  Lazy l  Type Safe

19

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;        }  }    

20

Property Declaration

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;        }  }    

21

Setter Method (Convenience)

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;        }  }    

22

Getter Method (Convenience)

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;        }  }    

23

Property Fetcher (Lazy Construction)

Properties in Java

public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {          firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstName  ==  null  ?  null  :  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }  }    

24

Even Lazier…

Properties in Java

public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {          firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstName  ==  null  ?  "Peter"  :  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName",  "Peter");          return  firstName;        }  }    

25

With initial value

Undirectional, Bidirectional and Lazy binding in Java

Demo Properties

Listeners

>  Change Listener l  Observable, old value, new value

>  Invalidation Listeners l  Observable

27

Property Listener Example

IntegerProperty  temperature  =  new  SimpleIntegerProperty(0);    temperature.setOnChangeListener(        new  ChangeListener<Number>()  {            public  void  change(                  ObservableValue<?  Extends  Number>  ov,                Number  newValue,  Number  oldValue)            System.out.printf(“%f  %f  %f”,                ov.doubleValue(),  oldValue.doubleValue(),                newValue.doubleValue()      }  );  temperature.set(2);  temperature.set(4);    

28

Hey Ho! This is all just to say:

var  temperature:  Integer  =  23  on  replace  oldValue  {      println("temperature={temperature},          oldValue={oldValue}");  }  //  Visage  (previously  JavaFX  Script)    

29

JavaFX 2.0 Observable Lists

>  Extends java.util.List >  Includes addListener/removeListener

>  For bulk operations use: l  addAll l  removeAll l  setAll

>  Sort with l  FXCollections.sort()

30

List Change Listener

list.addListener(new  ListChangeListener<Item>()  {      public  void  onChanged(Change<Item>  c)  {          while  (c.next())  {              if  (c.wasPermutated())  {                  for  (int  i  =  c.getFrom();  i  <  c.getTo();  i++)  {                      int  newLoc  =  getPermutation(i);                      //  handle  move  (a.k.a.  sort)                  }              }  else  {                  for  (Item  removed  :  c.getRemoved())  {                      //  handle  removal                  }  for  (Item  added  :  c.getAddedSubList())  {                      //  handle  addition                  }  }}}});  

31

JavaFX 2.0 Observable Maps

>  Extends java.util.Map  >  Includes addListener() / removeListener()  

>  MapChangeListener  l  Supports add()  / remove()  l  Can get associated:

l  Key l  Old Value l  New Value

32

Binding in JavaFX 2.0

>  One of the most important features of JavaFX 1.3 and prior

>  Now supported via an API (that works with Observable Properties)

>  Can handle most cases quite elegantly and with full type safety

33

Binding in JavaFX 2.0

Infix  Addition/Subtraction/Multiplication/Division:    

heightProperty().bind(rect1.heightProperty().add(rect2.heightProperty()));  

 Aggregate  Operators:    

widthProperty().bind(Bindings.max(rect1.widthProperty(),  rect2.widthProperty(),  rect3.widthProperty()));  

 Conditional  Expressions:    

strokeWidthProperty().bind(Bindings.when(hover).then(4).otherwise(0));  

 Bidirectional  Binding:    

heightProperty().bindBidirectional(rect1.heightProperty());  

34

Life is like a bowl of cherries

Demo Image Fracture

“The Scene-graph is King.”

36

Image

Image View 1

Image View 2

Image View 3

Image View 4

Image View Node

37

Media Player

Media View 1

Media View 2

Media View 3

Media View 4

Media

38

Breaking Glass

1.  Divide a bounded area into four triangles 2.  Are we there yet? 3.  For each triangle

A.  Choose a random side and split it to two rectangles

B.  Recursive descend the two triangles (step 2)

39

Controls

10 / 10 Break

Button Control

>  Simple Button Control >  Add and remove click event handler >  Support Cascading Style Sheets

41

Button Code

public  class  ButtonDemo  extends  AbstractDevoxxApplication  {      public  void  initialiseScene(Group  root)  {          VBox  vbox  =  VBoxBuilder.create().              spacing(25).layoutX(25).layoutY(25).build();          root.getChildren().add(vbox);          Button  red  =  ButtonBuilder.create()              .text("Red").style("-­‐fx-­‐base:  red;").build();          Button  yellow  =  ButtonBuilder.create()              .text("Yellow").style("-­‐fx-­‐base:  blue;")              .build();          Button  green  =  ButtonBuilder.create()              .text("Green").style("-­‐fx-­‐base:  green;")              .build();          vbox.getChildren().addAll(red,yellow,green);      }  /*  …  */  }    

42

TextField Control

>  One line entry text field control >  Set OnAction event handler >  Can listen to individual key events >  Support Cascading Style Sheets

43

TextField Demo

public  class  TextDemo  extends  AbstractDevoxxApplication  {      public  void  initialiseScene(Group  root)  {          VBox  vbox  =  VBoxBuilder.create().spacing(25)              .layoutX(25).layoutY(25).build();          root.getChildren().add(vbox);          TextField  red  =  TextFieldBuilder.create()              .text("Red  Devoxx")              .style("-­‐fx-­‐base:  red;  -­‐fx-­‐font-­‐size:  48pt;  ")              .build();          TextField  green  =  TextFieldBuilder.create()              .text("Green  Devoxx")              .style("-­‐fx-­‐base:  green;  -­‐fx-­‐font-­‐size:  24pt;  ")              .build();          vbox.getChildren().addAll(red,green);      }  /*….  */  }    

44

ListView Control

>  Displays a list of items >  Reuses cells for performance >  Default cell renderer can

display Strings >  For other object types

l  Create custom CellFactory

45

ListView Code

public  void  initialiseScene(Group  root)  {                VBox  vbox  =  VBoxBuilder.create()  

 .spacing(25).layoutX(25).layoutY(25).build();                root.getChildren().add(vbox);                  final  ListView<String>  listView  =    

   new  ListView<String>();              listView.setItems(FXCollections.observableArrayList(                      "Manchester  City",  "Manchester  United",                        "Newcastle  United",  "Chelsea",                        "Tottenham  Hotspur",  "Liverpool",  /*  …  */  ));                  

 listView.getSelectionModel()                        .setSelectionMode(SelectionMode.MULTIPLE);                vbox.getChildren().addAll(listView);          }          /*…*/  }  

46

TreeView Control

>  Displays a tree view of items >  Can dynamically populate as

tree is expanded >  Default cell renderer can

display Strings >  For other object types

l  Create custom CellFactory

47

TreeView Code

public  void  initialiseScene(Group  root)  {      /*…*/      TreeView  treeView  =  TreeViewBuilder.<String>create().root(          TreeItemBuilder.<String>create().value("JVM  Languages").children(              TreeItemBuilder.<String>create().value("Static").children(                  new  TreeItem<String>("Scala"),                  new  TreeItem<String>("Java"),                  new  TreeItem<String>("Visage"),  /*…*/              ).build(),              TreeItemBuilder.<String>create().value("Dynamic").children(                  new  TreeItem<String>("Clojure"),                  new  TreeItem<String>("Groovy"),  /*…*/              ).build(),  /*…*/          ).build()      ).build();      /*…*/  }   48

ToolBar Demo

>  Toolbar displays items horizontally or vertically >  Handles arbitrary number of items >  Can add any node to the toolbar, including

custom nodes >  Automatic adds an overflow hint if cannot display

all toolbar items

49

Toolbar Code

public  class  ToolBarDemo  extends  AbstractDevoxxApplication  {      public  void  initialiseScene(Group  root)  {          /*…*/          ToggleGroup  amFm  =  new  ToggleGroup();          ToolBar  toolBar  =  ToolBarBuilder.create().items(              new  Label("Volume"),              new  Slider(),              new  ToggleButton("Loudness"),              RadioButtonBuilder.create()                  .text("AM").toggleGroup(amFm).build(),              RadioButtonBuilder.create()                  .text("FM").toggleGroup(amFm).build(),              new  Button("Tune")          ).build();          vbox.getChildren().addAll(toolBar);  }}    

50

Progress Bars and Indicators

>  Progress Bars can be laid out vertically and horizontally

>  Progress Indicator is a circular widget

>  Progress Bar and Indicator can be indefinite

>  Double property 0.0 <= x <= 1.0

51

Progress Bar/Indicator Code

VBoxBuilder.create().spacing(10)      .alignment(Pos.CENTER).children(      new  ProgressBar(),      new  ProgressBar(.25),      new  ProgressIndicator(.75)  ).build()  

52

Accordion Control

>  Accordion is a space saving components

>  Accordian accept only TitledPanes

>  Each TitledPane managed one scenegraph node

>  Can choose the titled pane expanded by default

53

Accordion Code

String  imageUrl  =  new  Image(ResizableImageViewDemo.class.      getResource("images/Squirrel.jpg").toExternalForm();    Accordion  accordion  =  AccordionBuilder.create().panes(      new  TitledPane("Button",  new  Button("Regular")),      new  TitledPane("ToggleButton",  new  ToggleButton("Toggle")),          imagePane  =  new  TitledPane("SquirrelImage",                                      ImageViewBuilder.create().image(imageUrl,                                      500,  500,  true,  true,  false)          ).build()      )  ).build()  

54

TabPane Control

>  Alternative space saving component >  Choose a side for the Tab >  Each manages one component node >  Tab pane has two modes:

l  floating l  recessed

55

TabPane Code

Accordion  accordion;      TitledPane  imagePane;      TabPane  tabPane  =  TabPaneBuilder.create().tabs(          TabBuilder.create().text("Progress").content(              /*  Progress  Tab  Here  */          ).build(),          TabBuilder.create().text("Accordion").content(              /*  Accordion  Tab  Here  */          ).build()      ).build();  accordion.setExpandedPane(imagePane);  vbox.getChildren().addAll(tabPane);  

56

JavaFX Components

57

Pens, papers and inks, first!

58

A component is an encapsulation that binds a set of nodes with the operations that act on those nodes

59

Component Types

>  Non-Resizable l  javafx.scene.shape.Shape  l  javafx.scene.Group  

>  Resizable l  javafx.scene.layout.Pane  l  javafx.scene.layout.Region  l  javafx.scene.layout.Control  

60

Group based

>  Particularly using the JavaFX primitive nodes under javafx.scene.shape.*;

>  Design is not meant to be resized >  Layout is fixed at construction / initialisation time

61

Region based

>  Region is the sub class of javafx.scene.Parent  >  Adds the ability to resize a node, layout a

particular set of children

62

Control based

>  Allows particular subclass of Region that permits skinning of node with a stylesheet

>  You need 3 classes l  The Control java.scene.control.Control

l  The Skinnable java.scene.control.Skinnable

l  The Behaviour com.sun.javafx.scene.control.BehaviorBase

63

Control based contd

>  See JFXtras.org for more examples of skinnable components written for JavaFX 2.0

>  Define CSS file referencing a Skin class >  A Skin is a Region (JavaFX 2.0) com.sun.javafx.scene.control.BehaviorBase  com.sun.javafx.scene.control.SkinBase  

64

Skins are StackPanes

>  SkinBase is a type of StackPane  >  A StackPane is a Region >  Idea of shuffling a deck of cards and only showing

one

65

Layout Children Method

void  layoutChildren()  

>  Layout all of the children of a Region based component

>  Compute the preferred width and height of the children (first)

>  May cache those values internally as part of the component or use Constraints

66

Layout Boundaries

>  SDK will make a request to find the best width and height for your component.

>  Your component must do the same for its children >  Implement at least computePrefWidth and

computePrefHeight methods!

67

Layout Methods

protected  double  computePrefHeight(double  w)  {            return  child.prefHeight(w)  +  2  *ht;  }    protected  double  computePrefWidth(double  h)  {          return  child.prefWidth(h)  +  2  *  wt;  }  

68

Pedantic Complete

Implement the other four methods too >  computeMinWidth(v) >  computeMinHeight(v) >  computeMaxWidth(v) >  computeMaxHeight(v)

69

Demo Custom Border Layout

Writing JavaFX Containers

Event Input on Node

>  Mouse Events fall under the pointer iteraction (single) l  Clicked, Entered, Exited, Pressed, Dragged,

Released, Wheel l  Target Entered, Target Exited

>  Key Events l  Clicked, Pressed, Released

Event Input on Node

>  It is possible to consume an event and stop it bubbling further down the scene-graph hierarchy

>  You can block a component from event interaction >  Using clever tricks (opaque shape) you can

implement dialog / focus / modal behaviour

Layout Secrets

75

Reuse SDK Methods

Some SDK Methods

>  Region#layoutInArea()  >  Region#positionInArea()  >  Node#resize()  >  Node#resizeRelocate()  

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

A B

D E

C

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

>  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane

Built-in Layouts

Demo Box Container Pane

Tips

>  When Dragging a Node prefer to translate (X,Y) >  When Laying Out a Node prefer to set the position

with layoutX, layoutY >  Given steady state conditions you can swap

layout (X,Y) for translation (X,Y)

Tips 2

>  Use blocking boolean flags to prevent conflict when you animating children in a container

>  If you are unsure about MT concurrency you can always use AtomicBoolean

>  Prefer JavaFX Properties

88

Displaying HTML in JavaFX

Displaying HTML in JavaFX

public  class  WebViewDemo  extends  Application  {          public  static  void  main(String[]  args)  {                  launch(args);          }          @Override  public  void  start(Stage  stage)  {                  WebView  webView  =  new  WebView();                  webView.getEngine().load("http://devoxx.com");                  Scene  scene  =  new  Scene(webView);                  stage.setScene(scene);                  stage.setTitle("Web  View  Demo");                  stage.show();  }}  

89

For more info on Web/HTML5…

Moving to the Client – JavaFX and HTML5 Stephen Chin Kevin Nilson Thursday 10:50 AM, Room 7

90

10 / 10 Break

JavaFX With Groovy

Features of Groovy

>  Modern language l  Closures l  AST Transforms l  Strongly typed dynamic language

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

>  Declarative syntax with GroovyFX Builders l  Familiar to Groovy and JavaFX Script developers

Java vs. GroovyFX DSL

public  class  HelloStage  extends  Application  {        public  void  start(Stage  stage)  {          stage.setTitle("Hello  Stage");          stage.setWidth(600);          stage.setHeight(450);          Scene  scene  =  new  Scene();          scene.setFill(Color.LIGHTGREEN);          Rectangle  rect  =  new  Rectangle();          rect.setX(25);          rect.setY(40);          rect.setWidth(100);          rect.setHeight(50);          rect.setFill(Color.RED);          scene.setRoot(new  Group(rect));          stage.setScene(scene);          stage.show();      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }  }  

GroovyFX.start  {  stage  -­‐>      def  sg  =  new  SceneGraphBuilder(stage)        sg.stage(title:  “Hello  Stage”,  width:  600,  

height:  450)  {          scene(fill:  groovyblue)  {              rectangle(x:  25,  y:  40,  width:  100,  

height:  50,  fill:  red)          }      }  }    

93

21 Lines 430 Characters

8 Lines 180 Characters

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }  

94

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }    

95

Builder for GroovyFX scene graphs

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }  

96

Declarative Stage definition

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }  

97

Inline property definitions

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }  

98

Bind to properties

Disappearing Circles in Groovy

def  sg  =  new  SceneGraphBuilder()  def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }    sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {          50.times  {              circle(centerX:  rand(800),  centerY:  rand(600),                              radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {                  fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }  }  

99

Sequence Creation Via Loop

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.! } !}!  

100

Properties in GroovyFX

public class Person {! @FXBindable String firstName; ! @FXBindable String lastName;!}!  

101

Properties in GroovyFX

public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;!}!  

102

Optional initializers

Properties in GroovyFX

public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;!}!!def p = new Person()!def last = p.lastName!p.firstName = “Agent”!!

103

Get and set values

Properties in GroovyFX

public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;!}!!def p = new Person()!def last = p.lastName!p.firstName = “Agent”!!textField(text: bind(p.lastNameProperty()))!!

104

Access underlying property for binding

Binding in GroovyFX

@FXBindable  class  Time  {      Integer  hours      Integer  minutes      Integer  seconds        Double  hourAngle      Double  minuteAngle      Double  secondAngle        public  Time()  {          //  bind  the  angle  properties  to  the  clock  time          hourAngleProperty().bind((hoursProperty()  *  30.0)  +  

(minutesProperty()  *  0.5))          minuteAngleProperty().bind(minutesProperty()  *  6.0)          secondAngleProperty().bind(secondsProperty()  *  6.0)      }  }  

105

Animation in GroovyFX

timeline(cycleCount:  Timeline.INDEFINITE,  autoReverse:  true)  {  

   at  (1000.ms)  {          change(rect1,  'x')  to  200  tween  ease_both          change  rect2.yProperty()  to  200  tween  linear      }  }.play()  

106

Animation in GroovyFX

timeline(cycleCount:  Timeline.INDEFINITE,  autoReverse:  true)  {  

   at  (1000.ms)  {          change(rect1,  'x')  to  200  tween  ease_both          change  rect2.yProperty()  to  200  tween  linear      }  }.play()  

107

Easy animation syntax: at (duration) {keyframes}

Animation in GroovyFX

timeline(cycleCount:  Timeline.INDEFINITE,  autoReverse:  true)  {  

   at  (1000.ms)  {          change(rect1,  'x')  to  200          change  rect2.yProperty()  to  200      }  }.play()  

108

Key frame DSL

Animation in GroovyFX

timeline(cycleCount:  Timeline.INDEFINITE,  autoReverse:  true)  {  

   at  (1000.ms)  {          change(rect1,  'x')  to  200  tween  ease_both          change  rect2.yProperty()  to  200  tween  linear      }  }.play()  

109

Optional easing

Event Listeners in GroovyFX

>  Supported using the built-in Closure syntax >  Optional arguments for event objects

110

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

   }.play()  }  

Event Listeners in GroovyFX

Supported  using  the  built-­‐in  Closure  syntax  Optional  arguments  for  event  objects  

111

Compact syntax {body}

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

   }.play()  }  

Event Listeners in GroovyFX

Supported  using  the  built-­‐in  Closure  syntax  Optional  arguments  for  event  objects  

112

Optional event parameter {event -> body}

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

   }.play()  }  

TableView in Java

113

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);  

TableView in GroovyFX

114

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)  })  }  

Layout in Java

115

TextField  urlField  =  new  TextField(“h_p://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);  

Layout in GroovyFX

116

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") } } }

Layout in GroovyFX

117

Layout in GroovyFX

118

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")!}!

Layout in GroovyFX

119

GroovyFX Supports…

120

GroovyFX Supports…

121

122

JavaFX With Scala

What is Scala

>  Started in 2001 by Martin Odersky >  Compiles to Java bytecodes >  Pure object-oriented language >  Also a functional programming language

2001 •  Scala Started

2003/2004 •  Scala v1.0

2006 •  Scala v2.0

2011 •  Scala 2.9.0 (latest)

123

Why Scala?

>  Shares many language features with JavaFX Script that make GUI programming easier: l  Static Type Checking – Catch your errors at compile

time l  Closures – Wrap behavior and pass it by reference l  Declarative – Express the UI by describing what it

should look like

>  Scala also supports Type Safe DSLs! l  Implicit Conversions – type safe class extension l  Operator Overloading – with standard precedence rules l  DelayedInit / @specialized – advanced language

features

124

Java vs. Scala DSL

public  class  HelloStage  extends  Application  {        public  void  start(Stage  stage)  {          stage.setTitle("Hello  Stage");          stage.setWidth(600);          stage.setHeight(450);          Scene  scene  =  new  Scene();          scene.setFill(Color.LIGHTGREEN);          Rectangle  rect  =  new  Rectangle();          rect.setX(25);          rect.setY(40);          rect.setWidth(100);          rect.setHeight(50);          rect.setFill(Color.RED);          scene.setRoot(new  Group(rect));          stage.setScene(scene);          stage.show();      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }  }  

object  HelloJavaFX  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Hello  Stage"          width  =  600          height  =  450          scene  =  new  Scene  {              fill  =  LIGHTGREEN              content  =  Seq(new  Rectangle  {                  x  =  25                  y  =  40                  width  =  100                  height  =  50                  fill  =  RED              })          }      }  }  

125

21 Lines 430 Characters

17 Lines 177 Characters

Disappearing Circles in ScalaFX

object  DisappearingCircles  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)              }          }      }  }  

Disappearing Circles in ScalaFX

object  DisappearingCircles  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)              }          }      }  }    

127

Base class for JavaFX applications

Disappearing Circles in ScalaFX

object  DisappearingCircles  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)              }          }      }  }    

128

Declarative Stage definition

Disappearing Circles in ScalaFX

object  DisappearingCircles  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)              }          }      }  }  

129

Inline property definitions

Disappearing Circles in ScalaFX

object  DisappearingCircles  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)              }          }      }  }  

130

Sequence Creation Via Loop

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"  

131

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();  

132

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();  

133

JavaFX Script-like animation syntax: at (duration) {keyframes}

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();  

134

Operator overloading for animation syntax

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();  

135

Optional tween syntax

Event Listeners in Scala

>  Supported using the built-in Closure syntax >  Optional arguments for event objects >  100% type-safe

136

onMouseClicked  =  {      Timeline(at(3  s){radius-­‐>0}).play()  }  

Event Listeners in Scala

Supported  using  the  built-­‐in  Closure  syntax  Optional  arguments  for  event  objects  100%  type-­‐safe  

137

Compact syntax {body}

onMouseClicked  =  {      Timeline(at(3  s){radius-­‐>0}).play()  }  

Event Listeners in Scala

Supported  using  the  built-­‐in  Closure  syntax  Optional  arguments  for  event  objects  100%  type-­‐safe  

138

Optional event parameter {(event) => body}

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

About Project Visage

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

>  Come join the team! >  For more info: http://visage-lang.org/

139

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

How about JavaFX on… Visage

Stage  {      title:  "Hello  Stage"      width:  600      height:  450      scene:  Scene  {          fill:  Color.LIGHTGREEN          content:  Rectangle  {              x:  25              y:  40              width:  100              height:  50              fill:  Color.RED          }      }  }  

140

How about JavaFX on… Visage

Stage  {      title:  "Hello  Stage"      width:  600      height:  450      scene:  Scene  {          fill:  Color.LIGHTGREEN          content:  Rectangle  {              x:  25              y:  40              width:  100              height:  50              fill:  Color.RED          }      }  }  

141

How about JavaFX on… Visage

Stage  {      title:  "Hello  Stage"      width:  600      height:  450      Scene  {          fill:  Color.LIGHTGREEN          Rectangle  {              x:  25              y:  40              width:  100              height:  50              fill:  Color.RED          }      }  }  

142

Visage is JavaFX Script++

>  Default Parameters >  New Literal Syntax For:

l  Angles – 35deg,  4rad,  1turn  l  Colors – #DDCCBB,  #AA33AA|CC  l  Lengths – 5px,  2pt,  3in,  4sp  

>  Null-check Dereference l  var width = rect!.width

>  Built-in Bindable Maps (coming soon!) l  var fruitMap = ["red" : apple, "yellow" : banana] l  var fruit = bind fruitMap["red"]

143

Visage and JavaFX 2.0 are made for each other…

>  Enhanced Binding l  Retains lazy evaluation properties with additional

expressive power >  Integrated Collections

l  Sequences and Maps automatically convert between JavaFX Observable Lists/Maps

>  Built-in Animation Syntax l  Ties into JavaFX animation subsystem l  Provides consistent, clean APIs

144

Conclusion

>  You can write JavaFX applications in pure Java

>  JavaFX is also usable in alternate languages

>  You can get improved support using DSL libraries l  GroovyFX l  ScalaFX

>  Or a dedicated UI JVM Language l  Visage

Pro JavaFX 2 Platform Coming Soon!

>  Coming 1st Quarter 2012 >  All examples rewritten in

Java >  Covers the new JavaFX 2.0

APIs >  Will includes ScalaFX,

GroovyFX, and Visage

146

147

Professional Services

peter.pilgrim@gmail.com JavaFX 2.0 in Enterprises Financial Services in London Training with Consultancy Technical Leadership

JavaFX 2.0 – A Java Developer's Guide

Stephen Chin Chief Agile Methodologist, GXS http://steveonjava.com @steveonjava

Peter Pilgrim Oracle Java Champion http://www.xenonique.co.uk/blog/ @peter_pilgrim

Thank You

Attributions

All images are Creative Commons (CC) License from Flickr.com – “You must attribute the source and you cannot change the content” Tim Ellis http://www.flickr.com/photos/tim_ellis/ Lego Basics http://www.flickr.com/photos/tim_ellis/338755101/sizes/l/ *PaysImaginaire* http://www.flickr.com/photos/nevrlndtink/ Variable Plastic Bag http://www.flickr.com/photos/nevrlndtink/232906118/sizes/m/ ~Deiby http://www.flickr.com/photos/deiby/ Expression http://www.flickr.com/photos/deiby/5489382677/sizes/l/ Lisa Sinclair http://www.flickr.com/photos/plumandjello/ fruit http://www.flickr.com/photos/plumandjello/2333263539/sizes/l/ Nerovivo http://www.flickr.com/photos/dominik99/ http://www.flickr.com/photos/dominik99/407716865/sizes/z/in/photostream/

Attributions

All images are Creative Commons (CC) License from Flickr.com – “You must attribute the source and you cannot change the content” .Guilty http://www.flickr.com/photos/roll_initiative/ Arbitrary Function Generator http://www.flickr.com/photos/roll_initiative/3278642272/ Loop Oh Rupert Grazer http://www.flickr.com/photos/loop_oh/ Pattern at the Senckenberg Museum in Frankfurt am Main / Germany. http://www.flickr.com/photos/loop_oh/4571485915/ Lili Vieira de Carvalho, Vancouver, Canada http://www.flickr.com/people/lilivc/ Composition of Bowls http://www.flickr.com/photos/lilivc/367582911/sizes/l/ Mykl Roventine http://www.flickr.com/people/myklroventine/ 19/365 Game Over http://www.flickr.com/photos/myklroventine/3210068573/sizes/l/ superciliousness / Bentley Smith http://www.flickr.com/people/superciliousness/ 200510 carpenter's tools - inside the workman's shed - all his old tools

http://www.flickr.com/photos/superciliousness/57486288/

Attributions

All images are Creative Commons (CC) License from Flickr.com – “You must attribute the source and you cannot change the content” You’ve got a fast car http://www.flickr.com/photos/coreforce/5910961411/ Core Force http://www.flickr.com/photos/coreforce/ GAME AT MARBLES http://www.flickr.com/photos/9619972@N08/928099769/sizes/l/in/photostream/ (Author unknown, from an antique children's boo Lucs Game http://www.flickr.com/photos/9619972@N08/928099769/ just.Luc http://www.flickr.com/people/9619972@N08/ DIY Easel http://www.flickr.com/photos/68888883@N00/2744696593/in/photostream/ Judy of the Woods http://www.flickr.com/people/68888883@N00/

Recommended