JavaFX 1.2 Top 10 and Migration Guide

31 05 2009

Note 1: I am following Jim Weaver’s lead, since he discovered JavaFX 1.2 is downloadable from javafx.com. Enjoy the new release!

Note 2: I have updated the section below on nativearray.  Please use with caution!

The JavaFX 1.2 release is a huge upgrade from 1.1, both in terms of functionality and API improvements.  This means there are lots of cool new things to take advantage of, but at the same time you will spend quite a lot of time migrating your applications.

Fortunately, after upgrading JFXtras, WidgetFX, and dozens of sample applications for the Pro JavaFX Platform book, I have this all down to a science.  In the rest of this blog I will take you through a whirlwind tour of the relevant new features, and most common migration hurdles so you can be up and running in record time!

First the fun stuff…  new features.  Here are the top 10 features you should start using today:

JavaFX Top 10 Revised

JavaFX Top 10 Features (revised)

1. Skinnable UI Controls

It is great to have some pure JavaFX controls, such as Button, ListView, ProgressBar, and Slider that don’t rely on Swing peers underneath.  An added advantage is that they are fully skinnable to match the fonts and color palette of your application.

2. New Layout Classes

The new layout classes including Tile, Stack, Flow, ClipView, and Panel are a very welcome addition!  The layout API has also gotten a lot cleaner, which makes it easier to write your own layouts, such as the JFXtras Grid.

3. Charting Support: Area, Bar, Bubble, Line, Pie, Scatter, X/Y

Now I can compete with my Flex buddies on business oriented RIAs!  The new charting and graphing support is a must for any enterprise applications, so I am glad to see it made the cut.

4. RSS/Atom Feed Support

Having built-in RSS/Atom feed support is a welcome addition, and will make it much easier to write feed-based applications that cleanly port from the desktop to mobile.

5. Local Data Storage

An easy way to save state between sessions, no Web Start API hacking required!  See the new Resource and Storage classes in the javafx.io package for details.

6. Stage Infrastructure: Screen and Alerts

There is some new functionality that makes it easy to pop-up alert dialogs, or work directly with the screen bounds.  While you could have done direct Swing/Java2D hacks before, this helps keep your code mobile safe.

7. Improved Asynchronous Processing Model

The new Task class supercedes the AsynchronousAbstractOperation with a clean API for calling long-running tasks.  The code running in the background has to be coded in Java, but if you are looking for a JavaFX alternative see the JFXWorker (which is part of the JFXtras project).

8. BoxBlur effect

Finally, a high-performance alternative to Gaussian blur.  This is now the default for DropShadow, which should speed up a lot of applications!

9. Math and Properties Classes

There are new JavaFX equivalents for java.lang.Math and java.util.Properties in the javafx.util package.  Make sure you use these instead so your application is portable to mobile.

10. High Performance Referencing of Java Arrays (updated!)

Java arrays are now optimized so that they can be used directly from JavaFX code without conversion to a sequence.  This can have a huge performance gain in programs transfering large models between Java and JavaFX code, and is transparent to the application developer.

Note: There is experimental support for direct creation of Java arrays in JavaFX using the nativearray keyword.  Use with caution, because this functionality may be removed at any time.

 Now that you are incentivized to upgrade, it is time to figure out how to migrate your existing applications.

The Definitive 1.2 Migration Guide

If you have made it this far, you are a serious JavaFX hacker!  This section covers the most common language, functionality, and API changes that you will encounter when migrating applications from JavaFX 1.1.  If you notice anything that is not covered, feel free to add it in the comments and I will update the guide as appropriate.

General:

  • JavaFX 1.2 is not binary compatible – If you use any jars or third-party JavaFX libraries (such as JFXtras), they must be recompiled for the new release or you will get compilation errors.  Speaking of JFXtras, a new version which has been updated for JavaFX 1.2 is nearly ready, and will be announced here when it is complete!
  • All internal-only APIs are broken – More details broken out by section below, but if you rely on any impl_ or com.sun packages, your code will definitely need to be updated.
  • Linux and Solaris are now supported – This is more of a feature than a migration issue, but if you have users on multiple platforms you can now proudly state that Linux is supported.

Language Changes:

  • No more variable shadowing in nested blocks – It previously was valid to name a variable the same in both the inner and outer block of an expression.  The variable in the inner block would simply replace the one in the outer.  However, this will throw a compiler error in JavaFX 1.2.  The fix is simple…  just use a different variable name.
  • Use Mixins instead of Multiple Inheritance – JavaFX no longer supports multiple inheritance.  Instead you can extend one class and as many mixins as you like.  Mixins are like interfaces in Java, except they can have variables and implementations that are shared by all the classes that extend them.  The only change you have to make in your application to start using mixins is to add the mixin keyword when you define a new class like this:
public mixin class Resizable { /* variables and functions here */ }
  • Commas are required in sequences – Sequences now require commas between elements (except those that end in braces).  This is a little less convenient, but actually a very good thing, because it avoids several language pitfalls that were hard to track down before.

Node Changes:

  • Node.boundsInScene is gone – This was removed for performance reasons, fortunately there is an easy replacement that offers the same functionality:
node.localToScene(node.boundsInLocal)
  • Node.focusable -> Node.focusTraversable – Small API change, but good to know when you get the compilation error on focusable not found.  This is part of a larger focus fix where any Node that is visible, focusTraversable, and not disabled will be eligible for focus (a key listener is no longer required).
  • CustomNode.create() gets called before init – Previously the CustomNode create() method would get called after init and before postinit.  Now that it gets called even earlier than init, some of your code may not work correctly.  Make sure that any variables you are depending upon in the create() method are either initialized inline or have a bind declaration so they get updated once set.
  • SwingControl.enabled -> Node.disable – There is a new disable flag on the Node class that is used universally across all controls to enable or disable them.  This conflicted with the old SwingControl.enabled variable, which has now been removed.
  • Rectangle2D -> Bounds – All references to Rectangle2D have been changed to the new javafx.geometry.Bounds class, which may have a ripple effect through your code.

Layout Changes:

  • min/max/pref -> getters – All of the Resizable methods (minimumWidth, minimumHeight, maximumWidth, maximumHeight, preferredWidth, preferredHeight) have been replace with function getters (getMinWidth, getMinHeight, getMaxWidth, getMaxHeight, getPrefWidth, getPrefHeight respectively).  The prefWidth/Height functions take an extra parameter, which is the amount of space in the opposite dimension.  This is very useful for doing height or width constrained layouts, such as Flows, but can be ignored by passing -1.
  • impl_layoutX/Y -> layoutX/Y – The impl_layoutX and impl_layoutY methods have been replaced with official layoutX and layoutY variables.  It is recommended that you use these variables over translateX/Y if you are moving nodes into position.
  • impl_requestLayout() -> requestLayout() – The requestLayout function has similarly moved from an internal to a public API.
  • impl_layout -> doLayout() – Rather than having a function to set the layout on, you now override Parent.doLayout().
  • Panel class added for declarative layouts – If you are looking for a functional alternative to Container, take a look at the new Panel class, which lets you set the layout declaratively.  It also has variables to override the default min/max/pref values without subclassing Container.
  • New functions on Container to help with layouts – There are a whole slew of new functions on the Container class that make it easier to work with the new layout system.  Make sure to read through them, because they will both save you time and help you follow the best practices for layout design.
  • Different transformation order – Previously the transforms[] variable allowed you to apply transformations included in the layoutBounds, while scaleX/translateX/rotate etc. were applied after layout.  Now both transforms[] and the transformation variables are calculated after layout uniformly.

Skin/Control Changes:

  • Skin.scene -> Skin.node – The name of the Node on Skin has changed from scene to node, which helps reduce confusion with the Scene class.
  • Skin.compute* methods removed – There were a series of computePreferredWidth/Height/etc. methods that were removed.  Instead you can directly use the getPrefWidth/Height/etc. methods on the Resizable class mentioned above.
  • Skin is now abstract – The Skin class is now abstract, and required that you implement your own contains and intersects methods.  You can either do this by using the new JFXtras AbstractSkin class or using the following boilerplate code:
override function contains(localX:Number, localY:Number):Boolean {
    return node.contains(localX, localY);
}

override function intersects(localX:Number, localY:Number, localWidth:Number, localHeight:Number):Boolean {
    return node.intersects(localX, localY, localWidth, localHeight);
}
  • New Behavior class – There is a new Behavior class that is meant to be used together with Control and Skin to provide reusable behaviors.
  • TextBox.text -> rawText, TextBox.value -> text – There was some swizzling of variables on the TextBox class.  What used to be text changed to rawText, and value now has the same semantics text used to have.

Asynchronous Changes:

  • RemoteTextDocument has been removed – Use HttpRequest directly instead.
  • AbstractAsyncOperation has been removed – Use the new Task infrastructure instead for communcating with Java code running in a background thread.

Animation Changes:

  • Transition.interpolate -> Transition.interpolator – A small name change to make room for a new interpolate flag that allows you to turn on or off interpolation altogether.
  • Transition now extends Timeline – This is a welcome change, which makes it much easier to work with Transitions and Timelines together.  To support this change ParallelTransition and SequentialTransition now take a sequence of Timeliens.

Java Equivalent Functions:

  • java.lang.Math -> javafx.util.Math – There is a new JavaFX math library, which is a drop-in replacement for the Java math library.  The main advantage of using the new JavaFX math library is that all functions are supported on mobile devices (including pow, log, etc.).
  • java.lang.Properties -> javafx.util.Properties – Another class that is similar in functionality to the Java equivalent, but portable to mobile.  Be warned, however, that the JavaFX properties file format is not the same as the standard Java properties file format.

CSS Changes:

  • CSS Update Defect (RT-4817) – Stylesheet updates no longer affect newly added Nodes due to a known defect.  In the meantime, you can do this to force a stylesheet refresh:
def senators = bind model.senators on replace {
    delete sceneRef.stylesheets;
    sceneRef.stylesheets = "{__DIR__}styles.css";
}
  • CheckBoxSkin.textFill doesn’t accept styles (RT-4819) – The check mark will pick up the style you set, but the text won’t.  The workaround for now is to create a checkbox with empty text and add a text node beside it with the correct styling and event handlers.
  • Can’t update the skin property of Control from CSS (RT-4820) – Another bug in the skin support.  You can set this in code instead for now.

Production Suite:

  • UiStub -> FXDNode – UiStub has been replaced with FXDNode, which includes some extra functionality, such as backgroundLoading, and placeholder images.

Miscellaneous:

  • Image.fromBufferedImage() removed – This has moved to SwingUtils.toFXImage().  Remember that if you use this function it will limit portability to mobile devices.
  • Color.fromAWTColor() removed – Yet another AWT-ism that has been removed. The JavaFX Color class is pretty thorough, so there shouldn’t be any reason to work with AWT Colors.
  • Duration.toDate is gone – As far as I know there is no equivalent functionality, but you can always get a duration’s value as a long and manipulate it directly.
  • Different variable names for the Affine class – If you use the Affine class, then your code is likely to break due to the new, more descriptive, method names, but the functionality is the same.

Whew!  …that was quite a lot to take in.  If you are interested to read more about the JavaFX 1.2 release including the new controls, layouts, and other functionality, the best source is to checkout the Pro JavaFX book that Jim, Dean, Weiqi, and I are writing.  It is almost fully updated for the JavaFX 1.2 release, and is available in Alpha right now from the book website.

I want to give a special thanks to Richard Bair and Amy Fowler from the Sun JavaFX team for providing a lot of valuable information on the JavaFX 1.2 release along the way.

Happy hacking on JavaFX 1.2!


Actions

Information

19 responses

31 05 2009
Danno Ferrin

Why isn’t something like JFXWorker in the core? Even CLDC has a Thread class, and encouraging people to drop down to Java for async work just encourages them from leaving the javafx script environment. As much as they are not promoting accessing the stack from anayehere but JavaFX Script you’de think they’de want to make it so you can do all you need to there.

31 05 2009
peterpilgrim

Thanks for the input and this blog, Stephen
This looks like welcome news. I anticipated that a javafx.io.* would be created on a AudioBoo podcast. I will more to say when get my hands on the new API. Did the JavaFX team mention any API or developments of remoting / serialisation of JavaFX objects to a server?

Thanks

1 06 2009
steveonjava

I had a chat with Josh about remoting over the weekend… In my opinion making it easy to hook up to web services is good (which they have done), but for those with Java on the backend it should be a seamless integration. This is definitely on the todo list for a future JFXtras release.

31 05 2009
JavaFX for GNU/Linux has arrived « The Art of Software Development

[…] and in case you have some JavaFX code from pre-1.2 versions, here’s how to migrate it. Possibly related posts: (automatically generated)JavaFX : Top 10 Things to KnowFuture of […]

31 05 2009
JavaOne, JavaFX 1.2, JavaFX Studio plug-in for Eclipse, Flamingo | Maxa Blog

[…] 1.2 was released over the weekend. There is now official support for Linux. Here is a great post with all the details from Stephen Chin. Check out Dzone JavaFX Refcard also from […]

31 05 2009
Eric Wendelin

Yes! Linux and Solaris support FTW!

31 05 2009
Buentello

nice update but Flex and Silverlight are still miles ahead in terms of maturity of tools, features and adoption. I don’t see why sun is still wasting time on JavaFX.

11 06 2009
zammbi

JavaFX objectives are much different compared to flex and silverlight.
JavaFX is for targeting all screens: desktop, browser, mobile, TV, blueray, etc
without changing any code.
Later on JavaFX will support full 3d also.
Also be able to sell JavaFX apps at the Java store.
I for one hope the JavaFX team to keeps up the good work.

1 06 2009
The Java FX Journey » Blog Archive » A 3x JavaFX Speed Up

[…] JavaFX 1.2 Top 10 and Migration Guide – This guide points out the top ten changes, and gives tips on how to migrate the code […]

2 06 2009
JavaFX-Update – Der Schockwellenreiter

[…] eine Menge verändert, weswegen sich das Upgrade lohnen dürfte. So hebt Stephen Chin in seiner Top 10 der neuen Funktionen in seinem Blog unter anderem anpassbare UI Controls, neue Layout-Klassen (Tile, Stack, Flow, […]

2 06 2009
JavaFX 1.2 wydana | itnews

[…] Chin na swoim blogu wymienia 10 najważniejszych zmian w nowym wydaniu: 1. Kontrolki interfejsu użytkownika obsługujące […]

13 06 2009
JavaFX 1.2 程序迁移指南

[…] 本文系经原作者Stephen Chin授权翻译,英文原文:The Definitive 1.2 Migration Guide,为方便起见,英文原文的副本可参见这里。 […]

13 06 2009
steveonjava

Kudos to Henry Zhang for the Chinese translation!

14 06 2009
JavaFX 1.2 迁移指南(英文)

[…] Chin的英文文章The Definitive 1.2 Migration Guide,中文翻译参见这里。 Below is the JavaFX 1.2 migration guide written by Stephen Chin. The […]

16 06 2009
The Java FX Journey » Blog Archive » A Game Programming Perspective

[…] release, and why they’re important. At the time I didn’t do this because there are many good articles elaborating the features, so I thought it would be redundant. After some time though, I […]

17 06 2009
WidgetFX 1.2 Beta Announcement « Steve on Java

[…] 3. Upgrade the rest of your code to be JavaFX 1.2 compatible. This is beyond the scope of this article, but I happen to know an excellent migration guide: http://steveonjava.com/2009/05/31/javafx-1-2-top-10/ […]

7 11 2009
Lee

Hi Steve,

Grate guide this has really helped me out, thank you very much.

Although I am struggling with one aspect the “use Mixins instead of Multiple Inheritance”. Once I use “Public mixin class” I am no longer able to use “extends CustomNode, BoardSquareInterface”. Because it gives me an error within NetBeans, do you know any way I could get around this?

I have included the code that worked with javafx 1.1 below:

public class BoardSquare extends CustomNode, BoardSquareInterface {
public var pieceWidth : Number;
public var pieceHeight : Number;
public-init var positionX : Integer;
public-init var positionY : Integer;
public var content : Piece;
public-init var board : Board;

def square = Rectangle
{
x: bind positionX * pieceWidth;
y: bind positionY * pieceHeight;
width: bind pieceWidth;
height: bind pieceHeight;
fill: Color.LIGHTGOLDENRODYELLOW;
}
public function getXPixel() : Number
{
return positionX * pieceWidth;
}

public function getYPixel() : Number
{
return positionY * pieceHeight;
}

override function create():Node {
return square;
}

override function getX() : Integer
{
return positionX;
}

override function getY() : Integer
{
return positionY;
}

override function isOccupied() : Boolean
{
return (content != null);
}
}

Any help at all would be greatly appreciated.

Many thanks,
Lee

7 11 2009
steveonjava

Lee,

Glad you found the guide useful!

A mixin can only extend other mixins or Java interfaces. Since BoardSquare extends CustomNode you can’t use it as a mix-in.

You could define BoardSquareInterface as a mixin (or subclass it with a new mixin) and provide a default implementation for the methods.

7 11 2009
Lee

Brilliant Ill give that a go, thanks for the quick response.

Lee

Leave a reply to Eric Wendelin Cancel reply