The Java Fx Platform – A Java Developer’S Guide

6,694 views

Published on

Presented at Devoxx 2009 for the JavaFX Univerity Session. Also available online at Parleys.com.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
6,694
On SlideShare
0
From Embeds
0
Number of Embeds
3,294
Actions
Shares
0
Downloads
92
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

The Java Fx Platform – A Java Developer’S Guide

  1. 1. The JavaFX Platform – A Java Developer’s Guide<br />Stephen Chin<br />Inovis, Inc.<br />
  2. 2. About Your Presenter<br />Director SWE, Inovis, Inc.<br />Open-Source JavaFX Hacker<br />MBA<br />Belotti Award<br />UberScrumMaster<br />XP Coach<br />Agile Evangelist<br />WidgetFX<br />JFXtras<br />FEST-JavaFX<br />Piccolo2D<br />Java Champion<br />JavaOneRockstar<br />JUG Leader<br />Pro JavaFX Author<br />2<br />Family Man<br />Motorcyclist<br />
  3. 3. LearnFX and Win at Devoxx<br />Tweet to answer:<br />@projavafxcourse your-answer-here<br />3<br />
  4. 4. Part 1 - JavaFX Crash Course<br />var x = [&apos;x&apos;,&apos;o&apos;,&apos;v&apos;,&apos;e&apos;,&apos;d&apos;,&apos;x&apos;];<br />insert x[5] before x[0];<br />println(&quot;{reverse x[0..&lt;]}&quot;);<br />@projavafxcourse answer<br />
  5. 5. 1. Download JavaFX<br />http://javafx.com/<br />5<br />2. Run Your IDE<br /><ul><li>NetBeans (bundled)
  6. 6. Eclipse – ExadelJavaFX Studio</li></ul>3. Write Your First App<br />Hello Devoxx!<br /><ul><li>Step-by-Step Demo</li></ul>var x = [&apos;x&apos;,&apos;o&apos;,&apos;v&apos;,&apos;e&apos;,&apos;d&apos;,&apos;x&apos;];<br />insert x[5] before x[0];<br />println(&quot;{reverse x[0..&lt;]}&quot;);<br />@projavafxcourse answer<br />
  7. 7. Hello Devoxx!: Creating a Stage<br />Stage {<br /> title: &quot;Hello Devoxx!&quot;<br /> scene: Scene {<br /> content: [<br /> &quot;...&quot;<br /> ]<br /> }<br />}<br />6<br />var x = [&apos;x&apos;,&apos;o&apos;,&apos;v&apos;,&apos;e&apos;,&apos;d&apos;,&apos;x&apos;];<br />insert x[5] before x[0];<br />println(&quot;{reverse x[0..&lt;]}&quot;);<br />@projavafxcourse answer<br />
  8. 8. Hello Devoxx!: Displaying Images<br />ImageView {<br /> image: Image {<br />url: &quot;http://www.javoxx.com/download/attachments/1706305/Devoxx09.jpg&quot;<br /> }<br /> opacity: .5<br />}<br />7<br />var x = [&apos;x&apos;,&apos;o&apos;,&apos;v&apos;,&apos;e&apos;,&apos;d&apos;,&apos;x&apos;];<br />insert x[5] before x[0];<br />println(&quot;{reverse x[0..&lt;]}&quot;);<br />@projavafxcourse answer<br />
  9. 9. Hello Devoxx!: RSS Feed<br />varitems:Item[];<br />RssTask {<br /> interval: 30s;<br /> location: &quot;http://search.twitter.com/search.rss?q=devoxx&quot;<br />onItem: function(item) {<br /> insert item into items;<br /> }<br />}.start();<br />8<br />
  10. 10. Hello Devoxx!: VBox Layout<br />vartextBox:VBox;<br />textBox = VBox {<br />layoutX: 40<br />layoutY: 40<br /> spacing: 20<br /> content: &quot;...&quot;<br />}<br />9<br />
  11. 11. Hello Devoxx!: Displaying Text<br />content: bind for (item in items) {<br /> Text {<br />textOrigin: TextOrigin.TOP<br />textAlignment: TextAlignment.JUSTIFY<br />wrappingWidth: 520<br />font: Font.font(null, FontWeight.BOLD, 18)<br /> content: item.title<br /> }<br />}<br />10<br />
  12. 12. Hello Devoxx!: Animating Graphics<br />vartransTransition = TranslateTransition {<br /> duration: 2m<br /> node: bind textBox<br />fromY: 600<br />toY: -4000<br /> interpolator: Interpolator.LINEAR<br />repeatCount: Timeline.INDEFINITE<br />}<br />transTransition.play();<br />11<br />
  13. 13. Hello Devoxx!: Playing Audio<br />?<br />MediaPlayer {<br />autoPlay: true<br />repeatCount: MediaPlayer.REPEAT_FOREVER<br /> media: Media {<br /> source: &quot;http://blogs.sun.com/roller/resources/dcb/Java.mp3&quot;<br /> }<br />}<br />12<br />
  14. 14. 13<br />Hello Devoxx! Demo<br />
  15. 15. Resource: JavaFX API Documentation<br />14<br />http://java.sun.com/javafx/1.2/docs/api/<br />
  16. 16. 15<br />Part 2 - Comparing JavaFX and Java<br />var x = [&apos;x&apos;,&apos;o&apos;,&apos;v&apos;,&apos;e&apos;,&apos;d&apos;,&apos;x&apos;];<br />insert x[5] before x[0];<br />println(&quot;{reverse x[0..&lt;]}&quot;);<br />@projavafxcourse answer<br />
  17. 17. Language Similarities<br />Java is…<br />Statically typed<br />Compiled to bytecodes<br />Runs on the JVM<br />Has a large library<br />JavaFX is…<br />Statically typed<br />Compiled to bytecodes<br />Runs on the JVM<br />Can call Java libraries<br />16<br />
  18. 18. Language Differences<br />17<br />
  19. 19. Integrating JavaFX and Java<br />Calling Java from JavaFX<br />Can call Java interface or classes directly<br />Automatic conversion to and from Arrays and Collections<br />Can even extend Java interfaces and classes<br />Calling JavaFX from Java<br />Easiest way is to create a Java interface that JavaFX extends<br />Can invoke JavaFX as a script and get results back<br />18<br />
  20. 20. Datatype Support<br />19<br />
  21. 21. JavaFX Operators<br />20<br /><ul><li>Multiplication and division of two durations is allowed, but not meaningful
  22. 22. Underflows/Overflows will fail silently, producing inaccurate results
  23. 23. Divide by zero will throw a runtime exception</li></li></ul><li>JavaFX Operators (continued)<br />21<br />
  24. 24. Access Modifiers<br />22<br />
  25. 25. Data Binding<br />A variable or a constant can be bound to an expression<br />var x = bind a + b;<br />The bound expression is remembered<br />The dependencies of the expression is watched<br />Variable is updated<br />Regular binding: when dependencies change values<br />Lazy binding: when the variable is accessed<br />var x = bind lazy a+ b;<br />23<br />
  26. 26. What Bind Updates<br />var x = bind if(a) then b else c<br />x is updated if a or b or c changes<br />var x = bind for (i in [a..b]) { i * i }<br />Not everything is recalculated<br />If a = 1 and b = 2, x is [1, 4]<br />If b changes to 3, only the added element is calculated<br />24<br />1<br />4<br />9<br />
  27. 27. Binding to Expressions<br />Binding to a block<br />Bound block may contain any number of defs followed by one expression<br />Dependencies of block is backtraced from the expression<br />Binding to function invocation expression<br />Regular function: dependencies are parameters<br />Bound function: backtraced from final expression inside function<br />25<br />
  28. 28. Binding to Object Literals<br />var a = 3; var b = 4;<br />var p = bind Point { x: a, y: b };<br />var q = bind Point { x: bind a, y: b };<br />var r = bind Point { x: bind a, y: bind b };<br />When a changes:<br />p gets a new instance of Point<br />q and r keep the old instance with a new x value<br />r will never get a new instance of Point<br />(the outer bind in r is useless)<br />26<br />
  29. 29. Binding to Functions<br />Stage {<br /> def cModel = CircleModel {};<br />varsliderRef:Slider;<br /> scene:<br /> Scene {<br /> content: [<br /> Circle {<br /> radius: bind cModel.diameter / 2<br /> },<br /> Text {<br /> content: bind &quot;Diameter: {%3.0f cModel.diameter}&quot;<br /> },<br /> Text {<br /> content: bind &quot;Area: {%3.2f cModel.getArea()}&quot;<br /> },<br />sliderRef = Slider {<br /> value: bind cModel.diameter with inverse<br />}]}}<br />27<br />class CircleModel {<br />vardiameter:Number;<br /> bound function getArea():Number {<br />Math.PI * Math.pow(diameter / 2, 2);<br /> }<br />}<br />http://learnjavafx.typepad.com/weblog/javafx_app_deployment/<br />
  30. 30. JavaFX Sequences<br />Represents collections of homogeneous data<br />A fundamental container data type<br />Rich set of language facilities<br />Contributor to declarative syntax<br />Automatic conversion to and from Java Arrays and Collections<br />28<br />
  31. 31. Creating Sequences<br />Explicit sequence expression<br />[1, 3, 5, 7, 9]<br />Elements are separated by commas<br />Comma may be omitted if element ends with brace<br />29<br />1<br />3<br />5<br />7<br />9<br />
  32. 32. Creating Sequences<br />Numeric sequence with range expressions:<br />[1..10]<br />Can have a step:<br />[1..10 step 2]<br />[0.0..0.9 step 0.1]<br />Can be decreasing:<br />[10..1 step -3]<br />Beware of step that goes opposite direction:<br />[10..1] is []<br />Exclusive right end<br />[1..&lt;5]<br />30<br />1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />1<br />3<br />5<br />7<br />9<br />0<br />.1<br />.2<br />.3<br />.4<br />.5<br />.6<br />.7<br />.8<br />.9<br />10<br />7<br />4<br />1<br />1<br />2<br />3<br />4<br />
  33. 33. Getting Information from Sequences<br />ints = [1, 3, 5, 7, 9]<br />sizeofintsis 5<br />ints[0] is 1, ints[1] is 3, ..., ints[4] is 9<br />ints[-1] is 0 (default value of Integer), so is ints[5]<br />For a sequence of objects, the default is null<br />31<br />1<br />3<br />5<br />7<br />9<br />[0]<br />[1]<br />[2]<br />[3]<br />[4]<br />
  34. 34. Getting Slices From Sequences<br />ints = [1, 3, 5, 7, 9]<br />ints[0..2] is [1, 3, 5]<br />ints[0..&lt;2] is [1, 3]<br />ints[2..] is [5, 7, 9]<br />ints[2..&lt;] is [5, 7]<br />ints[2..0], ints[-2..-1], ints[5..6] are all []s<br />32<br />1<br />3<br />5<br />7<br />9<br />[0]<br />[1]<br />[2]<br />[3]<br />[4]<br />
  35. 35. Getting Subsets from Sequences<br />ints = [1, 3, 5, 7, 9]<br />ints[k | k &gt; 6] is:<br />[7, 9] (k &gt; 6 is a condition)<br />ints[k | indexof k &lt; 2] is:<br />[1, 3]<br />ints[k | k &gt; 10] is:<br />[]<br />33<br />1<br />3<br />5<br />7<br />9<br />[0]<br />[1]<br />[2]<br />[3]<br />[4]<br />
  36. 36. Inserting into Sequences<br />ints = [1, 3, 5, 7, 9]<br />insert 20 into ints<br />insert 30 before ints[2]<br />insert 40 after ints[4]<br />insert [50, 60] into ints<br />34<br />1<br />3<br />5<br />7<br />9<br />1<br />3<br />5<br />7<br />9<br />20<br />1<br />3<br />5<br />7<br />9<br />20<br />30<br />1<br />3<br />5<br />7<br />9<br />20<br />30<br />40<br />1<br />3<br />5<br />7<br />9<br />20<br />30<br />40<br />50<br />60<br />
  37. 37. Deleting from Sequences<br />ints = [1, 3, 5, 7, 9]<br />delete 7 from ints<br />delete ints[0]<br />delete ints[0..1]<br />delete ints: ints becomes []<br />35<br />1<br />3<br />5<br />7<br />9<br />1<br />3<br />5<br />7<br />9<br />1<br />3<br />5<br />9<br />3<br />5<br />9<br />9<br />
  38. 38. Sequence Puzzlers<br />FX<br />What is the size of this sequence:<br />[1..10 step -1]<br />What does this evaluate to:<br />[10..&lt;20 step 2][k|k&gt;17]<br />What is the size of this sequence:<br />sizeof [20..1 step -3]<br />36<br />1<br />A: 0<br />2<br />A: [18]<br />3<br />A: 1<br />
  39. 39. Reference: JavaFXRefCard<br />37<br />http://refcardz.dzone.com/refcardz/<br />
  40. 40. Demo by Tor Norbye<br />38<br />JavaFX Builder Tool<br />?<br />
  41. 41. 39<br />JavaFX 1.2 Layouts<br />
  42. 42. JavaFX 1.2 Custom Layouts<br />Container<br />Panel<br />Both Extend Parent<br />Container creates layouts by extension<br />Panel creates layouts by declaration<br />40<br />
  43. 43. Who is My Representative?<br />41<br />Web Service Integration<br />
  44. 44. Calling a REST Service<br />REST URL:<br />http://whoismyrepresentative.com/getall_mems.php?zip=90210&output=json<br />Output:<br />{ &quot;results&quot;: [<br /> { &quot;type&quot;: &quot;rep&quot;, &quot;name&quot;: &quot;Henry A. Waxman&quot;, &quot;party&quot;: &quot;D&quot;, &quot;state&quot;: &quot;CA&quot;, &quot;district&quot;: &quot;30&quot;, &quot;phone&quot;: &quot;(202) 225-3976&quot;, &quot;office&quot;: &quot;2204 Rayburn&quot;, &quot;link&quot;: &quot;http://www.henrywaxman.house.gov/&quot; }<br />]}<br />42<br />
  45. 45. Making an HttpRequest<br />req = HttpRequest {<br /> method: HttpRequest.GET<br /> location: url<br />onInput: parseResponse<br />onDone: function() {<br /> if (req.responseCode != 200) {<br /> message = req.responseMessage;<br /> } else if (sizeof senators == 0 and sizeof representatives == 0) {<br /> message = &quot;No members found for {zipcode}&quot;;<br /> }<br /> }<br />onException: function(ex: java.lang.Exception) {<br />println(&quot;Exception: {ex.getClass()} {ex.getMessage()}&quot;);<br /> }<br />}<br />req.start();<br />43<br />
  46. 46. Using the Pull Parser<br />while (parser.event.type != PullParser.END_DOCUMENT) {<br />parser.seek( &quot;type&quot; );<br /> if (parser.event.type == PullParser.START_VALUE) {<br />parser.forward();<br /> if (parser.event.text == &quot;rep&quot;) {<br />var rep = Representative{}<br />parseMemberOfCongress( rep, parser );<br /> insert rep into representatives;<br /> } else if (parser.event.text == &quot;sen&quot; ) {<br />varsen = Senator{}<br />parseMemberOfCongress( sen, parser );<br /> insert sen into senators;<br />} } }<br />44<br />
  47. 47. JavaFX Mobile Development<br />
  48. 48. JavaFX Mobile Advantages<br />Write Once, Run Anywhere<br />Desktop, Mobile, Set-top Boxes (future)<br />Large Embedded Base<br />Built on top of Java ME platform<br />Wide Range of Devices<br />Runs on Feature Phones, Smart Phones<br />Currently available for Windows Mobile devices<br />
  49. 49. JavaFX Mobile Constraints<br />Screen Size<br />Your application has to be capable of adapting to different screen sizes as small as 320 by 240.<br />Common Profile<br />Mobile applications are limited to the JavaFX APIs that are part of the Common Profile, which is a subset of the Desktop Profile.<br />Performance<br />Mobile applications run on much less powerful devices, so they have less CPU and memory resources available to work with.<br />
  50. 50. Developing for the Common Profile<br />
  51. 51. Changes to Improve Hello Devoxx!<br />It runs as is with no changes, but was not designed for the mobile format.<br />We can do better:<br />Replace all hard-coded sizes with a bind<br />Scale the background image to the screen size<br />Put an error up on network failure<br />The improved version also works on the desktop.<br />49<br />
  52. 52. Mobile Demo<br />Hello Devoxx!<br />
  53. 53. JavaFX How-To’s<br />51<br />http://javafx.com/learn/howto.jsp<br />
  54. 54. 52<br />JFXtras – Open Source JavaFXAddons<br />http://jfxtras.org/<br />
  55. 55. JFXtras Grid<br />53<br />Row<br />Row<br />
  56. 56. JFXtras Grid<br />XGrid {<br /> effect: Reflection {}<br /> border: 20<br />vgap: 12<br />hgap: 12<br /> rows: bind [<br /> row([text, progressBar]),<br /> row([navigator, mediaGrid])<br /> ]<br />}<br />54<br />
  57. 57. Media Explorer Example<br />55<br />
  58. 58. JFXtras Borders<br />56<br />
  59. 59. JFXtras Borders<br />Function:<br />override function create() {<br />XTitledBorder {<br /> id: &quot;imageTitle“<br /> title: file.getName()<br /> content: XFrameBorder {<br /> id: &quot;imageFrame“<br /> node: XImageView {<br />preserveRatio: true<br /> smooth: true<br /> image: bind image<br /> }<br /> }<br /> }<br />}<br />CSS:<br />#imageTitle {<br /> position: &quot;bottom&quot;;<br /> justification: &quot;center&quot;;<br /> font: bold 12pt Serif;<br /> text-color: #000060;<br />}<br />#imageFrame {<br /> border-left-width: 12;<br /> border-top-width: 12;<br /> border-bottom-width: 20;<br /> border-right-width: 12;<br /> background-fill: #00007020;<br />}<br />57<br />
  60. 60. JFXtras Borders<br />58<br />
  61. 61. 59<br />MigLayout for JavaFX<br />
  62. 62. 60<br />Flexible Grid-Based Layout<br />Flow<br />Wrap<br />
  63. 63. MigLayout Constraints<br />“wrap”<br />“fill”<br />“flowy”<br />“gap”<br />MigLayout {<br /> constraints: “fill, wrap”<br /> // to be continued<br />}<br />61<br />
  64. 64. MigLayout {<br /> constraints: &quot;fill, wrap&quot;<br /> columns: &quot;[][]&quot;<br /> rows: &quot;[][]4mm[]push[]&quot;<br /> content: [<br /> Label {<br /> text: &quot;Email&quot;<br />layoutInfo: nodeConstraints( &quot;ax right&quot; )<br /> }<br />TextBox {<br />layoutInfo: nodeConstraints( &quot;growx, pushx&quot; )<br /> }<br /> Label {<br /> text: &quot;Password&quot;<br />layoutInfo: nodeConstraints( &quot;ax right&quot; )<br /> }<br />TextBox {<br />layoutInfo: nodeConstraints( &quot;growx, pushx&quot; )<br /> }<br /> Button {<br /> text: &quot;Login&quot;<br />layoutInfo: nodeConstraints( &quot;skip, right&quot; )<br /> }<br /> Label {<br /> text: &quot;This text is &apos;pushed&apos; to the bottom&quot;<br />layoutInfo: nodeConstraints( &quot;span&quot; )<br /> }<br /> ]<br />}<br />62<br />
  65. 65. JFXtras Shapes<br />63<br /> Almond Intersection of two circles (VesicaPiscis) centerX, centerY, width<br /> Arrow Arrow shape x, y, width, height, depth, rise<br /> Asterisk Asterisk with rounded corners centerX, centerY, width, radius, beams, roundness<br />AstroidHypocloid with four cusps centerX, centerY, radius<br /> Balloon Rectangular shape with a tab x, y, width, height, arc, anglePosition, tabWidth,<br />tabHeight, tabLocation, tabDisplacement<br /> Cross Symmetrical cross shape centerX, centerY, width, radius, roundness<br /> Donut Regular polygon with a hole centerX, centerY, innerRadius, outerRadius, sides<br />Lauburu Four comma-shaped heads centerX, centerY, radius<br />Continued…<br />
  66. 66. JFXtras Shapes (continued)<br />64<br />MultiRoundRectangle Rectangle with configurable corners x, y, width, height, topLeftWidth/Height,<br />topRightWidth/Height, bottomLeftWidth/Height,<br />bottomRightWidth/Height<br /> Rays Multiple rays extend from center centerX, centerY, rays, radius, extent, rounded<br />RegularPolygon Polygon with equal sides centerX, centerY, sides, radius<br />ReuleauxTriangle Curved triangle shape centerX, centerY, radius<br />RoundPin Cone with rounded top centerX, centerY, height, radius<br /> Star2 Multipoint star centerX, centerY, innerRadius, outerRadius, count<br />ETriangle Equilateral triangle x, y, width<br />ITriangle Isosceles triangle x, y, width, height<br /> RTriangle Right triangle x, y, width, height, anglePosition<br />
  67. 67. JFXtras Shapes<br />65<br />
  68. 68. Sphere Challenge<br />66<br />Andres Almiray’s Weblog<br />http://www.jroller.com/aalmiray/entry/griffon_gfxbuilder_fxbuilder_side_by<br />“The following snapshot shows a couple of spheres drawn with GfxBuilder and FxBuilder, can you guess which one is which?<br />…<br />This is by no means a post to bash JavaFX<br />rather to point out some of its deficiencies”<br /> -- Andres Almiray<br />(taken completely out of context)<br />
  69. 69. Sphere Challenge – JavaFX Response<br />Composition:<br />RadialGradient for the Sphere <br />Three additional RadialGradients for the light sources <br />A blurred shadow underneath<br />Features:<br />All Bound/Relative Coordinates<br />Configurable –<br />Base, Ambient, Specular, Shine Colors<br />Shadow Size and Height<br />Uses New JFXtrasColorUtil Library<br />JavaFX Caching for High Performance<br />67<br />Will be shipped with JFXtras 0.6<br />
  70. 70. JFXtras Spheres Demo<br />68<br />
  71. 71. JFXtras Shelf<br />69<br />
  72. 72. The JavaFX Desktop Widget Platform<br />WidgetFX<br />
  73. 73. WidgetFX Origins<br />71<br />
  74. 74. 72<br />Why WidgetFX Matters<br />
  75. 75. Movie Widget Tutorial<br />
  76. 76. Widget Properties<br />74<br />
  77. 77. Widget Definition<br />var widget: Widget;<br />widget = Widget {<br /> width: 640<br /> height: 352<br />aspectRatio: bind player.media.width<br /> / player.media.height<br /> content: bind player<br />}<br />75<br />
  78. 78. Load the Media<br />var source = &quot;http://projavafx.com/movies/ elephants-dream-640x352.flv&quot;;<br />var player = bind SimpleMoviePlayer {<br /> media: Media {<br /> source: source<br /> }<br /> width: bind widget.width<br /> height: bind widget.height<br />}<br />76<br />
  79. 79. Run in Widget Runner<br />77<br />
  80. 80. Widget Configuration Properties<br />78<br />
  81. 81. Widget Configuration<br />widget = Widget {<br /> ...<br /> configuration: Configuration {<br /> properties: [<br />StringProperty {<br /> name: &quot;source“<br /> value: bind source with inverse<br /> }<br /> ]<br /> scene: Scene {…} // see next page<br /> }<br />}<br />79<br />
  82. 82. Widget Config Dialog<br />Scene {<br /> content: XGrid {<br /> rows: row([<br /> Text {<br /> content: &quot;Source URL:“<br /> },<br />TextBox {<br /> columns: 30,<br /> value: bind source with inverse<br /> }<br /> ])<br /> }<br />}<br />80<br />
  83. 83. Add an On-Replace Trigger<br />var player = bind SimpleMoviePlayer {<br /> media: Media {<br /> source: source<br /> }<br /> width: bind widget.width<br /> height: bind widget.height<br />} on replace =oldPlayer {<br />oldPlayer.player.stop();<br />}<br />81<br />
  84. 84. Widget Configuration (demo)<br />82<br />
  85. 85. WidgetFX Contest Results!<br />3rd Place<br />Infix WeatherWidget<br />Larry Dickson<br />2nd Place<br />RadioFX<br />Yannick Van Godtsenhoven<br />1st Place<br />ScreenshotFX<br />Pär Dahlberg<br />83<br />
  86. 86. JavaFXpert RIA Exemplar Challenge<br />&quot;Create an application in JavaFX that exemplifies the appearance and behavior of a next-generation enterprise RIA (rich internet application)&quot;.<br />Grand Prize: $2,000 USD<br />(split between a two-man graphics artist and application developer team)<br />Deadline: 10 January, 2010<br />For more info: http://learnjavafx.typepad.com/<br />84<br />
  87. 87. LearnFX and Win at Devoxx<br />85<br />
  88. 88. Thursday’s Question<br />HttpRequest {<br /> location: http://steveonjava.com/<br />onResponseMessage: function(m) {<br />println(m); FX.exit()<br />}}.start();<br />Launch LearnFX from my blog: http://steveonjava.com/<br />Or tweet @projavafxcourse answer<br />2:00PM Room 8 (right here!)<br />86<br />
  89. 89. Sneak Preview of Thursday’s Session<br />87<br />
  90. 90. 88<br />Thank You<br />Stephen Chin<br />http://steveonjava.com/<br />Tweet: steveonjava<br />Thanks to my co-authors, Jim, Weiqi , and Dean for content included in this talk!<br />

×