Home >
These days new technologies are springing up from nowhere all the time. If it's not this month's epoch-defining new platform from Google, then another open source project will have developed a further spin on communicating with databases. On average, somewhere in the world, a new platform, framework, API or language is born every 23 minutes -- and that's a genuine statistic (granted, one I just made up!)
Unless you focus on only a particular platform, it can be a struggle to keep up with all the latest arrivals, plus their quirky project names. Wave, Prism, Nile, Gumbo, Bindows, Qooxdoo -- it's like trying to read the game board at the World Dyslexic Scrabble Championships. So how can we, as programmers, maintain the illusion of being on top of the daily twists and turns in the RIA space?
One technology, who's name is oft whispered in shadowy recesses wherever RIA fans gather, is JavaFX. But few outside the Java community really understand what it is, or appreciate what makes it so different to its rivals. As it happens, I've just finished writing a book about JavaFX, and now I have a bit of spare time on my hands I thought I'd give the uninitiated the benefit of my hard-earned accumulated wisdom. What follows is a JavaFX cheat sheet, complete with pro and anti comments to liberally sprinkle into any conversation, next time the topic comes up. If used wisely, they should convince your colleagues you actually know what the hell you're talking about.
"Still using separate shampoo and conditioner?"
JFX (to use its familiar name) is the Java camp's grandiose attempt to unite desktop, web, mobile, TV, and just about any other platform with a screen. At its heart is a new domain specific programming language, known as JavaFX Script. Despite the misleading suffix, code is compiled (not interpreted) to Java bytecode, giving JFX unhindered interaction with the countless APIs currently available for the Java platform. But JavaFX Script is more than just a rehash of Java, or any other JVM language; it is designed from the ground up to meet the specific needs of RIAs.
If you've working with other RIA technologies you might be expecting a dual-language approach. Typically the core of the user interface is declared using one language (often a variant of XML), and the code that brings it alive is written in other (JavaScript, or some clone, being a favourite). But JavaFX Script dispenses with this schizophrenic approach, in favour of a single declarative style which suits both purposes.
Let's have a look at an example:
def radius:Number = 50;
var n:Circle = Circle {
centerX: radius
centerY: radius
radius: radius
fill: Color.GREEN
}
Circle is a standard JFX class for representing a circle on-screen. You'll note the object, n, is created without the use of a constructor -- creation, and the assigning of instance variables, is done in one neat declarative nugget. This one-step process permits complex structures to be assembled, using a tree of nested object declarations, without resorting to a separate markup language.
Pro JavaFX Bluffer: "A single language that can accommodate both structure and behaviour is a great idea. Combining the two will surely pay even greater dividends as the technology matures."
Anti JavaFX Bluffer: "Well, it's certainly a novel idea, but isn't the industry already wedded to the dual-language approach? The best technology doesn't always win -- remember VHS vs Betamax?"
Express yourself
JavaFX Script is an expression language, meaning most of its constructs generate a result. This fits in nicely with the declarative syntax, as the next snippet of code demonstrates:
def radius:Number = 50;
var n:Group = Group {
content: for(c:Color in [Color.RED,Color.ORANGE,Color.GREEN])
Circle {
layoutY: indexof c * radius*2
centerX:radius centerY:radius
radius:radius
fill: c
}
}
A Group is a container for holding on-screen objects, its children are stored in its content sequence variable. Because JavaFX Script operates in either a declarative or procedural mode, we can use a for loop to populate the Group. This works because the for construct is an expression -- it returns an object on each pass, creating a result.
The square bracket syntax (highlighted in red) declares a sequence of objects to iterate over. In this example we're using the colours red, orange, and green, the colours of a traffic signal. A Circle is created for each color (shifted vertically by an appropriate amount each time, to create a column), and appended to the content of the Group.
Pro JavaFX Bluffer: "What's nice about JavaFX Script's expression syntax is that I can create highly dynamic UIs, with the logic placed right next to the part of the UI it affects."
Anti JavaFX Bluffer: "The expression language syntax is quite unlike the usual procedural code most developers are used to. Do the benefits really merit learning yet another language?"
Not such a bind after all
The Model/View/Controller implementation in some languages is incredibly clumsy. Java, for example, requires a model class to represent the data being observed, a listener interface for interested parties to receive notifications, and (optionally) an event class to describe the nature of any change.
Instead of this palarva, wouldn't it be nice if the view just expressed the relationship it had with any data it depends upon? Nicer still if that relationship was then automatically maintained, without the developer having to lift a finger.
def radius:Number = 50;
def loCols:Color[] = [
Color.RED , Color.ORANGE , Color.GREEN
];
def hiCols:Color[] = [
Color.PINK , Color.YELLOW , Color.LIGHTGREEN
];
var n:Group = Group {
content: for(i in [0..2]) {
def cir:Circle = Circle {
layoutY: i * radius*2
centerX:radius centerY:radius
radius:radius
fill: bind if(cir.hover) hiCols[i] else loCols[i]
}
}
}
We'd like each of our traffic signal circles to light up whenever the mouse enters them. At the head of the code we define two colour sequences, one for the normal colours, and the other for highlight colours. Instead of iterating over a sequence of Colors, we create an integer range from 0 to 2 (highlighted in red).
In the body of each Circle we bind the fill colour to the circle's hover variable (blue highlighted code), which is true when the mouse is inside the shape, and false otherwise. Bound expressions are re-evaluated whenever data they depend upon changes -- in this case any change to hover will cause the circle's colour to update. The update is performed automatically, without need for prompting.
JavaFX Script allows bound expressions to be as complex as necessary, including numerous variable references to different objects, and even function calls, so long as the result is compatible with the variable being assigned. Binds can also support a two-way relationship, but only at the expense of a greatly simplified expression.
[You can see the traffic signal example running, here]
Pro JavaFX Bluffer: "Binds mean my MVC code isn't strewn across various event handlers. If I want to know what influences any part of a UI, I need look no further than the code that defines it."
Anti JavaFX Bluffer: "Although binds are fairly efficient, there's a noticeable performance penalty if you use them excessively. True, it's improving with each compiler release, but will binds ever be a serious solution for really large scale applications, like word processors or spreadsheets?"
Minimal effort
Bind updates use something called minimal recalculation, meaning only those parts of a bound expression that are influenced by the data that has changed will be re-evaluated. Everthing else uses a cached value.
A bind can be used to control entire sections of the user interface, not just single variables. But while binds permit our UI to respond to changes from its model, updates emanating from the actual UI itself are handled using familiar procedural-style event handlers.
def radius:Number = 50;
def originalCols:Color[] = [
Color.RED , Color.ORANGE , Color.GREEN
];
var cols:Color[] = originalCols;
var n:Group = Group {
content: bind for(c:Color in cols)
Circle {
layoutY: indexof c * radius*2
centerX:radius centerY:radius
radius:radius
fill: c
}
onMouseClicked: function(ev:MouseEvent) {
cols = if(sizeof cols == 2)
for(i in [0,1,2]) originalCols[i]
else
for(i in [0,2]) originalCols[i];
}
}
Not all traffic signals use red, amber (orange), and green -- some just use red and green. The code above toggles between showing two or three lights, with every mouse click.
The Circles are controlled by the sequence cols. Whenever something inside the Group is clicked, the event handler function (blue highlight) runs, changing the contents of the cols sequence. Just like for, the if construct is also an expression. In our example it returns a sequence of Colors to cols, based upon the contents of originalCols. Depending upon the current size of cols, either all three colours are used, or just the first and third.
Because of the bind that controls the for loop (red highlight), the entire UI updates whenever the state of cols changes.
Pro JavaFX Bluffer: "Imagine being able to hide/disable entire sections of a UI by merely flipping the appropriate boolean variable -- or restyling an interface, live, by just reassigning one set of colour, font and geometry variables. Cool!"
Anti JavaFX Bluffer: "The problem with binds, and their minimal recalculation, is they can take an awful lot of getting used to. Very occasionally things don't update when you instinctively expect them to, because you've underestimated how clever JFX is at avoiding work it thinks is unnecessary. Conversely, sometimes too much will update (wasting CPU cycles), because you've defined the scope of the bind too wide, and triggered a cascade of changes, only some of which were necessary. Sure, it's easy to avoid these problems, but it takes experience and some understanding of binding mechanics."
And finally...
So that's it for now. Next time we'll look at how JavaFX applications can wander between desktop, web, mobile, and TV, without requiring a re-write. Although, if there's any particular topic you'd like explored, or any specific pro/anti JavaFX retort you need to put down a colleague, then feel free to leave suggestions.
If this blog has piqued your interest, and you want to know more, there are a number of fine JavaFX books available -- including (plug) my own! My book is slightly unusual, in that it doesn't seek to cover every nook and cranny of JavaFX (the documentation's on-line anyway), but focuses on explaining core JFX concepts through (fun!) real world projects, one per chapter. This practical solution-driven approach should make interesting reading for curious users of rival platforms, as well as those seriously considering becoming JFX developers.
'till next time...




Facebook Application Development
Simon,
I still follow your blog at http://www.java.net/blogs/javakiddy/ and congrats on finishing your book! I would like to know the best way to purchase your book (I would like to do a book review). Either through the Manning Meap process, Amazon, etc. I also will be looking forward to following you on twitter.
Would a keyword 'unbind' ever be necessary in the language?
Thanks!
-Carl
Glad to hear the book is finished. I bought the MEAP early this year and I can't wait to see the finished work.
I like the article too, though I think you've got a typo at the start of the second paragraph of "Not such a bind after all". I believe "palarva" should be "palaver"
Waiting for the next article,
Burk
Hi Simon,
Good to see this post with nice explanation.
Gonna buy the book soon..
Thanks for the book man.. Will expect more on this series.