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 Peter Pilgrim @steveonjava @peter_pilgrim Football, Music & Partner Family Man Motorcyclist
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
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 http://blogs.oracle.com/chrisoliver/entry/epitaph 4
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 Internet Explorer 7 and 8 with Service Pack 3 Chrome Windows Vista Home Basic, Home Internet Explorer 7, 8, and 9 Premium, Business, and Ultimate with Firefox 3.5, 3.6, and 4 Service Pack 2 Chrome Windows 7 Home Premium, Internet Explorer 8 and 9 Professional, and Ultimate Firefox 3.5, 3.6, and 4 Chrome 9
Supported Graphics Cards Supported Graphics Processing Graphics Card 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();   19 Lines        Scene  scene  =  new  Scene(root,  400,  250,  Color.ALICEBLUE);          Text  text  =  new  Text();   Characters 425        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
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(   25 Lines            GroupBuilder.create().children(              TextBuilder.create()                  .x(105)   418 Characters                .y(120)                  .text("Hello  Devoxx")                  .font(new  Font(30))                  .build()              ).build()          )      .build());      primaryStage.show();   }   13
Hello Devoxx (GroovyFX Version) GroovyFX.start  {  primaryStage  -­‐>      def  sg  =  new  SceneGraphBuilder()      sg.stage(          title:  'Hello  Devoxx',          show:  true)  {              scene(                  fill:  aliceblue,   17 Lines                width:  400,                  height:  250)  {   Characters 190                    text(                          x:  105,                          y:  120,                          text:  "Hello  Devoxx"                          font:  "30pt")                  }          }   }   14
Hello Devoxx (ScalaFX Version) object  HelloDevoxx  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Hello  Devoxx"          width  =  400          height  =  250          scene  =  new  Scene  {              fill  =  BLUE   Lines 16            Text  {   163 Characters                x  =  105                  y  =  120                  text  =  "Hello  Devoxx"                  font  =  Font(size:  30)              }          }      }   }   15
Hello Devoxx (Visage Version) Stage  {      title:  "Hello  Devoxx"      width:  400      height:  250      scene:  Scene  {          fill:  BLUE   14 Lines        content:  Text  {  Characters 129            x:  105              y:  120              text:  "Hello  Devoxx"              font:  Font  {size:  30pt}          }      }   }   16
Architecture of JavaFX 2.0 JavaFX Public API Quantum Toolkit Prism Glass Media Web WinTk Engine Engine Java2D Open GL D3D Java Virtual Machine
JavaFX 2.0 Fundamentals Properties, Lists, Binding 18
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 Property Declaration 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
Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {          firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstNameProperty().get();   Setter Method    }   (Convenience)    public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     21
Properties in Java public  class  Person  {      private  StringProperty  firstName;   Getter Method    public  void  setFirstName(String  val)  {   (Convenience)        firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     22
Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {   Property Fetcher        firstNameProperty().set(val);   (Lazy Construction)    }      public  String  getFirstName()  {          return  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     23
Properties in Java public  class  Person  {      private  StringProperty  firstName;   Even Lazier…    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
Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {   With initial value        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
Demo Properties Undirectional, Bidirectional and Lazy binding in Java
Listeners >  Change Listener l  Observable, old value, new value >  Invalidation Listeners l  Observable 2 7
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.heig htProperty()));     Aggregate  Operators:     widthProperty().bind(Bindings.max(rect1.widthProperty(),   rect2.widthProperty(),  rect3.widthProperty()));     Conditional  Expressions:     strokeWidthProperty().bind(Bindings.when(hover).then(4).oth erwise(0));     Bidirectional  Binding:     heightProperty().bindBidirectional(rect1.heightProperty());   34
Demo Image Fracture Life is like a bowl of cherries
“The Scene-graph is King.” 36
Image View Node Image View 1 Image View Image 2 Image View 3 Image View 4 37
Media View 1 Media View 2 Media Player Media Media View 3 Media View 4 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) 3 9
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   6 0
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 6 1
Region based >  Region is the sub class of javafx.scene.Parent   >  Adds the ability to resize a node, layout a particular set of children 6 2
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 6 3
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   6 4
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 6 5
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 6 6
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! 6 7
Layout Methods protected  double  computePrefHeight(double  w)  {            return  child.prefHeight(w)  +  2  *ht;   }     protected  double  computePrefWidth(double  h)  {          return  child.prefWidth(h)  +  2  *  wt;   }   6 8
Pedantic Complete Implement the other four methods too >  computeMinWidth(v) >  computeMinHeight(v) >  computeMaxWidth(v) >  computeMaxHeight(v) 6 9
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
Reuse SDK Methods 75
Some SDK Methods >  Region#layoutInArea()   >  Region#positionInArea()   >  Node#resize()   >  Node#resizeRelocate()  
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 >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane A B C >  StackPane >  TilePane D E >  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
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
Displaying HTML in JavaFX 88
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 10 / 10 Break 90
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  {   GroovyFX.start  {  stage  -­‐>        def  sg  =  new  SceneGraphBuilder(stage)      public  void  start(Stage  stage)  {            stage.setTitle("Hello  Stage");      sg.stage(title:  “Hello  Stage”,  width:  600,          stage.setWidth(600);   height:  450)  {          stage.setHeight(450);          scene(fill:  groovyblue)  {          Scene  scene  =  new  Scene();              rectangle(x:  25,  y:  40,  width:  100,          scene.setFill(Color.LIGHTGREEN);   height:  50,  fill:  red)   21 Lines        Rectangle  rect  =  new  Rectangle();          rect.setX(25);   8 Lines        }      }   430 Characters        rect.setY(40);          rect.setWidth(100);          rect.setHeight(50);   }     180 Characters        rect.setFill(Color.RED);          scene.setRoot(new  Group(rect));          stage.setScene(scene);          stage.show();      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }   }   93
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)  {   Builder for GroovyFX scene        50.times  {   graphs            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
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),     Declarative Stage                          radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {   definition                fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }   }   96
Disappearing Circles in Groovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }     Inline property sg.stage(title:  'Vanishing  Circles',  show:  true)  {   definitions    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
Disappearing Circles in Groovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }   Bind to properties   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
Disappearing Circles in Groovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }     Sequence Creation Via sg.stage(title:  'Vanishing  Circles',  show:  true)  {   Loop    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
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”;! }!   Optional initializers 102
Properties in GroovyFX public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;! }! ! def p = new Person()! def last = p.lastName! Get and set values p.firstName = “Agent”! ! 103
Properties in GroovyFX public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;! }! ! def p = new Person()! def last = p.lastName! Access underlying p.firstName = “Agent”! property for binding ! textField(text: bind(p.lastNameProperty()))! ! 104
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()   Easy animation syntax: at (duration) {keyframes} 107
Animation in GroovyFX timeline(cycleCount:  Timeline.INDEFINITE,   autoReverse:  true)  {      at  (1000.ms)  {          change(rect1,  'x')  to  200          change  rect2.yProperty()  to  200      }   }.play()   Key frame DSL 108
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()   Optional easing 109
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()   }   110
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} 111
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()   }   112
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);   113
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)  })   }   114
Layout in Java 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);   115
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") } } } 116
Layout in GroovyFX 117
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")! }! 118
Layout in GroovyFX 119
GroovyFX Supports… 120
GroovyFX Supports… 121
JavaFX With Scala 122
What is Scala 2001 2006 •  Scala Started •  Scala v2.0 2003/2004 2011 •  Scala v1.0 •  Scala 2.9.0 (latest) >  Started in 2001 by Martin Odersky >  Compiles to Java bytecodes >  Pure object-oriented language >  Also a functional programming language 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  {   object  HelloJavaFX  extends  JFXApp  {        stage  =  new  Stage  {      public  void  start(Stage  stage)  {          title  =  "Hello  Stage"          stage.setTitle("Hello  Stage");          width  =  600          stage.setWidth(600);          height  =  450          stage.setHeight(450);          scene  =  new  Scene  {          Scene  scene  =  new  Scene();              fill  =  LIGHTGREEN          scene.setFill(Color.LIGHTGREEN);              content  =  Seq(new  Rectangle  {   21 Lines        Rectangle  rect  =  new  Rectangle();          rect.setX(25);          rect.setY(40);   17 Lines                x  =  25                  y  =  40                  width  =  100   430 Characters        rect.setWidth(100);          rect.setHeight(50);   177 Characters                height  =  50                  fill  =  RED          rect.setFill(Color.RED);              })          scene.setRoot(new  Group(rect));          }          stage.setScene(scene);      }          stage.show();   }      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }   }   125
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   Base class for JavaFX        scene  =  new  Scene  {   applications            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
Disappearing Circles in ScalaFX object  DisappearingCircles  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Disappearing  Circles"          width  =  800   Declarative Stage        height  =  600          scene  =  new  Scene  {   definition            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
Disappearing Circles in ScalaFX object  DisappearingCircles  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Disappearing  Circles"   Inline property        width  =  800          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)              }          }      }   }   129
Disappearing Circles in ScalaFX object  DisappearingCircles  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)              }          }      }   }   130
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();   JavaFX Script-like animation syntax: at (duration) {keyframes} 133
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();   Operator overloading for animation syntax 134
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 135
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()   }   136
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} 137
Event Listeners in Scala Supported  using  the  built-­‐in  Closure   syntax   Optional  arguments  for  event  objects   100%  type-­‐safe   Optional event parameter {(event) => body} onMouseClicked  =  {  (e:  MouseEvent)  =>      Timeline(at(3  s){radius-­‐>0}).play()   }   138
About Project Visage >  “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.” >  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
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
Professional Services peter.pilgrim@gmail.com JavaFX 2.0 in Enterprises Financial Services in London Training with Consultancy Technical Leadership 147
JavaFX 2.0 – A Java Developer's Guide Thank You Stephen Chin Peter Pilgrim Chief Agile Methodologist, GXS Oracle Java Champion http://steveonjava.com @steveonjava http://www.xenonique.co.uk/blog/ @peter_pilgrim
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/

Java FX 2.0 - A Developer's Guide

  • 1.
    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
  • 2.
    Meet the Presenters Stephen Chin Peter Pilgrim @steveonjava @peter_pilgrim Football, Music & Partner Family Man Motorcyclist
  • 3.
    This is aParticipatory 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
  • 4.
    At the endof 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 http://blogs.oracle.com/chrisoliver/entry/epitaph 4
  • 5.
    JavaFX 2.0 Platform ImmersiveDesktop 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.
  • 6.
  • 7.
    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
  • 8.
    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
  • 9.
    Windows OS Requirements OperatingSystem (32-Bit and 64-Bit) Browsers (32-Bit and 64-Bit) Windows XP Home and Professional Internet Explorer 7 and 8 with Service Pack 3 Chrome Windows Vista Home Basic, Home Internet Explorer 7, 8, and 9 Premium, Business, and Ultimate with Firefox 3.5, 3.6, and 4 Service Pack 2 Chrome Windows 7 Home Premium, Internet Explorer 8 and 9 Professional, and Ultimate Firefox 3.5, 3.6, and 4 Chrome 9
  • 10.
    Supported Graphics Cards Supported Graphics Processing Graphics Card 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
  • 11.
    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
  • 12.
    Hello Devoxx (JavaVersion) 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();   19 Lines        Scene  scene  =  new  Scene(root,  400,  250,  Color.ALICEBLUE);          Text  text  =  new  Text();   Characters 425        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
  • 13.
    Hello Devoxx (BuilderVersion) public  void  start(Stage  primaryStage)  {      primaryStage.setTitle("Hello  Devoxx");      primaryStage.setScene(SceneBuilder.create()          .width(400)          .height(250)          .fill(Color.ALICEBLUE)          .root(   25 Lines            GroupBuilder.create().children(              TextBuilder.create()                  .x(105)   418 Characters                .y(120)                  .text("Hello  Devoxx")                  .font(new  Font(30))                  .build()              ).build()          )      .build());      primaryStage.show();   }   13
  • 14.
    Hello Devoxx (GroovyFXVersion) GroovyFX.start  {  primaryStage  -­‐>      def  sg  =  new  SceneGraphBuilder()      sg.stage(          title:  'Hello  Devoxx',          show:  true)  {              scene(                  fill:  aliceblue,   17 Lines                width:  400,                  height:  250)  {   Characters 190                    text(                          x:  105,                          y:  120,                          text:  "Hello  Devoxx"                          font:  "30pt")                  }          }   }   14
  • 15.
    Hello Devoxx (ScalaFXVersion) object  HelloDevoxx  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Hello  Devoxx"          width  =  400          height  =  250          scene  =  new  Scene  {              fill  =  BLUE   Lines 16            Text  {   163 Characters                x  =  105                  y  =  120                  text  =  "Hello  Devoxx"                  font  =  Font(size:  30)              }          }      }   }   15
  • 16.
    Hello Devoxx (VisageVersion) Stage  {      title:  "Hello  Devoxx"      width:  400      height:  250      scene:  Scene  {          fill:  BLUE   14 Lines        content:  Text  {  Characters 129            x:  105              y:  120              text:  "Hello  Devoxx"              font:  Font  {size:  30pt}          }      }   }   16
  • 17.
    Architecture of JavaFX2.0 JavaFX Public API Quantum Toolkit Prism Glass Media Web WinTk Engine Engine Java2D Open GL D3D Java Virtual Machine
  • 18.
  • 19.
    JavaFX 2.0 Properties >  Primitive Properties >  Object Properties >  FX List Collection Properties >  Properties are: l  Observable l  Lazy l  Type Safe 19
  • 20.
    Properties in Java Property Declaration 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
  • 21.
    Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {          firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstNameProperty().get();   Setter Method    }   (Convenience)    public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     21
  • 22.
    Properties in Java public  class  Person  {      private  StringProperty  firstName;   Getter Method    public  void  setFirstName(String  val)  {   (Convenience)        firstNameProperty().set(val);      }      public  String  getFirstName()  {          return  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     22
  • 23.
    Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {   Property Fetcher        firstNameProperty().set(val);   (Lazy Construction)    }      public  String  getFirstName()  {          return  firstNameProperty().get();      }      public  StringProperty  firstNameProperty()  {            if  (firstName  ==  null)                firstName  =  new  SimpleStringProperty(this,  "firstName");          return  firstName;        }   }     23
  • 24.
    Properties in Java public  class  Person  {      private  StringProperty  firstName;   Even Lazier…    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
  • 25.
    Properties in Java public  class  Person  {      private  StringProperty  firstName;      public  void  setFirstName(String  val)  {   With initial value        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
  • 26.
    Demo Properties Undirectional, Bidirectional and Lazy binding in Java
  • 27.
    Listeners >  Change Listener l  Observable, old value, new value >  Invalidation Listeners l  Observable 2 7
  • 28.
    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
  • 29.
    Hey Ho! Thisis all just to say: var  temperature:  Integer  =  23  on  replace  oldValue   {      println("temperature={temperature},          oldValue={oldValue}");   }   //  Visage  (previously  JavaFX  Script)     29
  • 30.
    JavaFX 2.0 ObservableLists >  Extends java.util.List >  Includes addListener/removeListener >  For bulk operations use: l  addAll l  removeAll l  setAll >  Sort with l  FXCollections.sort() 30
  • 31.
    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
  • 32.
    JavaFX 2.0 ObservableMaps >  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
  • 33.
    Binding in JavaFX2.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
  • 34.
    Binding in JavaFX2.0 Infix  Addition/Subtraction/Multiplication/Division:     heightProperty().bind(rect1.heightProperty().add(rect2.heig htProperty()));     Aggregate  Operators:     widthProperty().bind(Bindings.max(rect1.widthProperty(),   rect2.widthProperty(),  rect3.widthProperty()));     Conditional  Expressions:     strokeWidthProperty().bind(Bindings.when(hover).then(4).oth erwise(0));     Bidirectional  Binding:     heightProperty().bindBidirectional(rect1.heightProperty());   34
  • 35.
    Demo Image Fracture Life is like a bowl of cherries
  • 36.
    “The Scene-graph is King.” 36
  • 37.
    Image View Node Image View 1 Image View Image 2 Image View 3 Image View 4 37
  • 38.
    Media View 1 Media View 2 Media Player Media Media View 3 Media View 4 38
  • 39.
    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) 3 9
  • 40.
  • 41.
    Button Control >  Simple Button Control >  Add and remove click event handler >  Support Cascading Style Sheets 41
  • 42.
    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
  • 43.
    TextField Control >  One line entry text field control >  Set OnAction event handler >  Can listen to individual key events >  Support Cascading Style Sheets 43
  • 44.
    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
  • 45.
    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
  • 46.
    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
  • 47.
    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
  • 48.
    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
  • 49.
    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
  • 50.
    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
  • 51.
    Progress Bars andIndicators >  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
  • 52.
    Progress Bar/Indicator Code VBoxBuilder.create().spacing(10)      .alignment(Pos.CENTER).children(      new  ProgressBar(),      new  ProgressBar(.25),      new  ProgressIndicator(.75)   ).build()   52
  • 53.
    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
  • 54.
    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
  • 55.
    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
  • 56.
    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
  • 57.
  • 58.
    Pens, papers and inks, first! 58
  • 59.
    A component isan encapsulation that binds a set of nodes with the operations that act on those nodes 59
  • 60.
    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   6 0
  • 61.
    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 6 1
  • 62.
    Region based >  Region is the sub class of javafx.scene.Parent   >  Adds the ability to resize a node, layout a particular set of children 6 2
  • 63.
    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 6 3
  • 64.
    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   6 4
  • 65.
    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 6 5
  • 66.
    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 6 6
  • 67.
    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! 6 7
  • 68.
    Layout Methods protected  double  computePrefHeight(double  w)  {            return  child.prefHeight(w)  +  2  *ht;   }     protected  double  computePrefWidth(double  h)  {          return  child.prefWidth(h)  +  2  *  wt;   }   6 8
  • 69.
    Pedantic Complete Implement theother four methods too >  computeMinWidth(v) >  computeMinHeight(v) >  computeMaxWidth(v) >  computeMaxHeight(v) 6 9
  • 70.
  • 71.
    Writing JavaFX Containers
  • 72.
    Event Input onNode >  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
  • 73.
    Event Input onNode >  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
  • 74.
  • 75.
  • 76.
    Some SDK Methods >  Region#layoutInArea()   >  Region#positionInArea()   >  Node#resize()   >  Node#resizeRelocate()  
  • 77.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 78.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 79.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 80.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 81.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane A B C >  StackPane >  TilePane D E >  GridPane
  • 82.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 83.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 84.
    Built-in Layouts >  AnchorPane >  BorderPane >  VBox/HBox >  FlowPane >  StackPane >  TilePane >  GridPane
  • 85.
  • 86.
    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)
  • 87.
    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 88
  • 89.
    Displaying HTML inJavaFX 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
  • 90.
    For more infoon Web/HTML5… Moving to the Client – JavaFX and HTML5 Stephen Chin Kevin Nilson Thursday 10:50 AM, Room 7 10 / 10 Break 90
  • 91.
  • 92.
    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
  • 93.
    Java vs. GroovyFXDSL public  class  HelloStage  extends  Application  {   GroovyFX.start  {  stage  -­‐>        def  sg  =  new  SceneGraphBuilder(stage)      public  void  start(Stage  stage)  {            stage.setTitle("Hello  Stage");      sg.stage(title:  “Hello  Stage”,  width:  600,          stage.setWidth(600);   height:  450)  {          stage.setHeight(450);          scene(fill:  groovyblue)  {          Scene  scene  =  new  Scene();              rectangle(x:  25,  y:  40,  width:  100,          scene.setFill(Color.LIGHTGREEN);   height:  50,  fill:  red)   21 Lines        Rectangle  rect  =  new  Rectangle();          rect.setX(25);   8 Lines        }      }   430 Characters        rect.setY(40);          rect.setWidth(100);          rect.setHeight(50);   }     180 Characters        rect.setFill(Color.RED);          scene.setRoot(new  Group(rect));          stage.setScene(scene);          stage.show();      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }   }   93
  • 94.
    Disappearing Circles inGroovy 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
  • 95.
    Disappearing Circles inGroovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }     sg.stage(title:  'Vanishing  Circles',  show:  true)  {      scene(fill:  black,  width:  800,  height:  600)  {   Builder for GroovyFX scene        50.times  {   graphs            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
  • 96.
    Disappearing Circles inGroovy 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),     Declarative Stage                          radius:  150,  stroke:  white,                              strokeWidth:  bind('hover',  converter:  hc))  {   definition                fill  rgb(rand(255),  rand(255),  rand(255),  0.2)                  effect  boxBlur(width:  10,  height:  10,  iterations:  3)              }          }      }   }   96
  • 97.
    Disappearing Circles inGroovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }     Inline property sg.stage(title:  'Vanishing  Circles',  show:  true)  {   definitions    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
  • 98.
    Disappearing Circles inGroovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }   Bind to properties   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
  • 99.
    Disappearing Circles inGroovy def  sg  =  new  SceneGraphBuilder()   def  hc  =  {  hover  -­‐>  hover  ?  4  :  0  }     Sequence Creation Via sg.stage(title:  'Vanishing  Circles',  show:  true)  {   Loop    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
  • 100.
    Properties in Java publicclass 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
  • 101.
    Properties in GroovyFX publicclass Person {! @FXBindable String firstName; ! @FXBindable String lastName;! }!   101
  • 102.
    Properties in GroovyFX publicclass Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;! }!   Optional initializers 102
  • 103.
    Properties in GroovyFX publicclass Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;! }! ! def p = new Person()! def last = p.lastName! Get and set values p.firstName = “Agent”! ! 103
  • 104.
    Properties in GroovyFX publicclass Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;! }! ! def p = new Person()! def last = p.lastName! Access underlying p.firstName = “Agent”! property for binding ! textField(text: bind(p.lastNameProperty()))! ! 104
  • 105.
    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
  • 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()   106
  • 107.
    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()   Easy animation syntax: at (duration) {keyframes} 107
  • 108.
    Animation in GroovyFX timeline(cycleCount:  Timeline.INDEFINITE,   autoReverse:  true)  {      at  (1000.ms)  {          change(rect1,  'x')  to  200          change  rect2.yProperty()  to  200      }   }.play()   Key frame DSL 108
  • 109.
    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()   Optional easing 109
  • 110.
    Event Listeners inGroovyFX >  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()   }   110
  • 111.
    Event Listeners inGroovyFX 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} 111
  • 112.
    Event Listeners inGroovyFX 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()   }   112
  • 113.
    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);   113
  • 114.
    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)  })   }   114
  • 115.
    Layout in Java 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);   115
  • 116.
    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") } } } 116
  • 117.
  • 118.
    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")! }! 118
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
    What is Scala 2001 2006 •  Scala Started •  Scala v2.0 2003/2004 2011 •  Scala v1.0 •  Scala 2.9.0 (latest) >  Started in 2001 by Martin Odersky >  Compiles to Java bytecodes >  Pure object-oriented language >  Also a functional programming language 123
  • 124.
    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
  • 125.
    Java vs. ScalaDSL public  class  HelloStage  extends  Application  {   object  HelloJavaFX  extends  JFXApp  {        stage  =  new  Stage  {      public  void  start(Stage  stage)  {          title  =  "Hello  Stage"          stage.setTitle("Hello  Stage");          width  =  600          stage.setWidth(600);          height  =  450          stage.setHeight(450);          scene  =  new  Scene  {          Scene  scene  =  new  Scene();              fill  =  LIGHTGREEN          scene.setFill(Color.LIGHTGREEN);              content  =  Seq(new  Rectangle  {   21 Lines        Rectangle  rect  =  new  Rectangle();          rect.setX(25);          rect.setY(40);   17 Lines                x  =  25                  y  =  40                  width  =  100   430 Characters        rect.setWidth(100);          rect.setHeight(50);   177 Characters                height  =  50                  fill  =  RED          rect.setFill(Color.RED);              })          scene.setRoot(new  Group(rect));          }          stage.setScene(scene);      }          stage.show();   }      }        public  static  void  main(String[]  args)  {          launch(HelloStage.class,  args);      }   }   125
  • 126.
    Disappearing Circles inScalaFX 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.
    Disappearing Circles inScalaFX object  DisappearingCircles  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Disappearing  Circles"          width  =  800          height  =  600   Base class for JavaFX        scene  =  new  Scene  {   applications            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
  • 128.
    Disappearing Circles inScalaFX object  DisappearingCircles  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Disappearing  Circles"          width  =  800   Declarative Stage        height  =  600          scene  =  new  Scene  {   definition            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
  • 129.
    Disappearing Circles inScalaFX object  DisappearingCircles  extends  JFXApp  {      stage  =  new  Stage  {          title  =  "Disappearing  Circles"   Inline property        width  =  800          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)              }          }      }   }   129
  • 130.
    Disappearing Circles inScalaFX object  DisappearingCircles  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)              }          }      }   }   130
  • 131.
    Binding in Scala InfixAddition/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
  • 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();   132
  • 133.
    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();   JavaFX Script-like animation syntax: at (duration) {keyframes} 133
  • 134.
    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();   Operator overloading for animation syntax 134
  • 135.
    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 135
  • 136.
    Event Listeners inScala >  Supported using the built-in Closure syntax >  Optional arguments for event objects >  100% type-safe onMouseClicked  =  {      Timeline(at(3  s){radius-­‐>0}).play()   }   136
  • 137.
    Event Listeners inScala 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} 137
  • 138.
    Event Listeners inScala Supported  using  the  built-­‐in  Closure   syntax   Optional  arguments  for  event  objects   100%  type-­‐safe   Optional event parameter {(event) => body} onMouseClicked  =  {  (e:  MouseEvent)  =>      Timeline(at(3  s){radius-­‐>0}).play()   }   138
  • 139.
    About Project Visage >  “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.” >  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
  • 140.
    How about JavaFXon… 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
  • 141.
    How about JavaFXon… 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
  • 142.
    How about JavaFXon… 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
  • 143.
    Visage is JavaFXScript++ >  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
  • 144.
    Visage and JavaFX2.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
  • 145.
    Conclusion >  You canwrite 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
  • 146.
    Pro JavaFX 2Platform 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 147
  • 148.
    JavaFX 2.0 –A Java Developer's Guide Thank You Stephen Chin Peter Pilgrim Chief Agile Methodologist, GXS Oracle Java Champion http://steveonjava.com @steveonjava http://www.xenonique.co.uk/blog/ @peter_pilgrim
  • 149.
    Attributions All images areCreative 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/
  • 150.
    Attributions All images areCreative 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/
  • 151.
    Attributions All images areCreative 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/