Skip to main content

Watched Pots and JavaFX

Posted by javakiddy on August 28, 2008 at 1:54 PM PDT

In recent weeks I've been immersed in the strange and exciting world of the JavaFX Preview release. Some might say up to my neck, although sometimes it's felt more like drowning. JavaFX makes a lot of previously very complex graphics tasks now very simple. At the same time it makes a lot of previously very simple tasks now frustratingly hard!

Of course, this is merely preview release one — another update is apparently scheduled for this November, so perhaps some headaches will be addressed by then. Here's hoping! But for now here's some random gripes, observations (and a little bit of interesting source code) relating to the current release.One of the main problems of developing using the recent preview release is the mass of outdated documentation, tutorials, and other such matter floating around on the Internet. JavaFX has been through a lot of changes and redesigns, with the current preview release being very different in both API and language syntax to the original F3-inspired platform which made its debut eighteen months ago at JavaOne 2007. When searching for any JavaFX related query one has to remember to always check the date when the resulting pages were posted, as pages relating to the old JFX seem to far outnumber the new.

While it's perfectly understandable that the various commentaries and examples scattered across the far flung corners of the internet are still available, some of the obsolete documentation seems to be hosted by Sun itself! [1][2] Surely they can spare a few moments to take it down, update it, or at least flag it as outdated?

Coding in JavaFX is really quite an enjoyable experience compared to hacking away at Swing. The declarative syntax is a real boon for getting stuff on screen quickly, and the timeline system takes all the pain out of getting things to animate. Perhaps this is why problems, when they do rear their ugly head, seem all the more acute?

Event handling was one example. JavaFX Script supports function types (variables which reference functions), and uses them for event handling. This means only one handler can be assigned to each event type. A clickable node (a button) might want to act on its own mouse clicks, for the purposes of animation, but also allow external classes to receive the click events too. The solution might be to create another event type, "action" for example, and republish the mouse click to the outside world as an action event. But if a subclass of the button then needs to know when action is fired, presumably yet another event type is needed to republish the action event(?)

I wondered whether I could chain event handlers, but this proved unworkable from within the declarative syntax. And besides, even if I'd gotten it to work, it would have been a clumsy solution. Some sort of event multiplexing would be useful, although quite how that would work I don't know. Sure, each event function type could become a sequence (array), but how does one append a function to said sequence declaratively?

It's not the end of the World — we can survive without an event mux! But can we survive without layout managers?

The scene graph model seems to be orientated more towards nodes having control over their own position and dimensions. Certainly many drawing primitives (circle, rectangle, image) permit some control, but the top level Node class, and containers like Group, do not. You can find out how big they are, but (short of scaling or clipping) can't request a particular size. At the moment only a couple of very basic layout classes are included; one look at their source exposes plenty of hooks into undocumented low-level mechanics from their Group/Node parents.

package jfxgui.layout;

import javafx.scene.Group;

public class GridBox extends Group
{ public attribute columns:Integer=1
on replace { impl_requestLayout(); }

init
{ impl_layout = doBoxLayout;
}

private function doBoxLayout(g:Group) : Void
{ var maxWidth:Number=0.0;
var maxHeight:Number=0.0;

for(n in content)
{ maxWidth = if(n.getBoundsWidth() > maxWidth)
n.getBoundsWidth() else maxWidth;
maxHeight = if(n.getBoundsHeight() > maxHeight)
n.getBoundsHeight() else maxHeight;
}

var i:Integer=0;
for(n in content)
{ var x = i mod columns;
var y = (i / columns).intValue();
n.impl_layoutX = x*maxWidth;
n.impl_layoutY = y*maxHeight;
i++;
}
}
}

The GridBox class above uses the same techniques as the scene graph's existing layout classes to reproduce AWT's GridLayout. You can see all the references to the undocumented impl_ attributes and functions, required to control content layout. The AWT GridLayout sizes its contents to identical dimensions, but I'm not aware of a safe/recommended way to do this with Nodes.

So is JavaFX a waste of space? Absolutely not! Don't get me wrong, JavaFX is a great technology, and JavaFX Script is shaping up nicely as a really cool DSL for graphics and effects programming. It's precisely because it gives you such a feeling of liberation that the problems, when encountered, stand out even more.

I've no doubt future releases of JFX will address much of the above, but with only a few months to go before the version 1.0 release, I just wonder how much of that (crucial, opinion forming) first release will be marked "coming soon"?

Related Topics >>

Comments

@tackline : I suppose I should have used Integer's for 'columns', 'i', 'x' and 'y', then I could have avoided the conversion.

I am also disappointed that no headway has been made in regards to layout managers. Free floating nodes are going to be more work to lay out and manage. Also with the addition of 3D shouldn't we be seeing some 3DLayoutManagers? Like "OrbitManager" or "CubeManager"?

{ var x = i mod columns; var y = (i / columns).intValue(); I'm not familiar with JavaFX. Just curious about the intValue() there. Does / give a double/Double result? So for instance 1/2 would be 0.5d? Is there not a div operator to go with mod?