Tuesday, May 20, 2008

Compiled JavaFX in Swing applications

[Update: I got this working with the JavaFX preview release - see this blog entry]

I've integrating interpreted JavaFX script widgets into Swing applications by using the Java 6 Scripting Engine to execute the script and have the JavaFX widget add its Canvas component to a passed in Swing parent component to allow it to integrate with the Swing application seamlessly.

So, after returning from JavaOne I was keen to integrate compiled JavaFX widgets in a similar way, to give better performance and easier deployment of multi-script JavaFX code. I thought it would be fairly simple, but I hit a few hurdles along the way.

My first idea was to extend a custom Java class in JavaFX to easily add the widget to Swing. I hit a snag when I couldn't figure out how to implement constructors in JavaFX that Java can recognise.

I tried things like:

public class javafxtest {
public function javafxtest(val1: String; val2 : String) : javafxtest {
return this;
}
}
But whatever I did in JavaFX, Java only saw an empty constructor and another that took a boolean.

So I gave up on that and just defined an interface in Java that I then implemented in JavaFX, and that went well for a while - it's easy enough to implement interfaces in JavaFX, and I could obtain a reference to the JavaFX implementation from Java and call methods on it. So, if I call a method on the JavaFX widget that returns a JComponent then I can add that as a child of a Swing container and have integration that way, right?

Well, maybe, but I seem to have a fundamental JavaFX problem that's stopping it working. The same code works when I run the JavaFX script from the command line:

public function setupCanvas() {
var c3:Canvas = Canvas {
content :
Text {
content: "A JavaFX widget!"
}
}
}
At runtime in my Swing application I get the following Exception when I call that JavaFX method:

Caused by: java.lang.NoSuchMethodError: javafx.ui.Canvas.(Z)V
at javafxtest.altiotest.setupCanvas$impl(altiotest.fx:77)
at javafxtest.altiotest.setupCanvas(altiotest.fx:28)
at javafxtest.altiotest.getControlComponent$impl(altiotest.fx:101)
And, er, that's as far as I can get.

I'm presuming this is because the JavaFX SDK is not finalised, that I'm using the latest OpenJFX compiler in a beta version of the Java6 JVM and I've finally tipped over the bleeding edge onto the other side where nothing works. But still, it should work, I think, so if anyone has any ideas please let me know.

2 comments:

Unknown said...

Hi, interesting entry and one of the very few on the topic - did you ever figure out how to achive the integrating JavaFX int Swing apps ?

Jim said...

Not so far, but I've switched jobs recently and just got back from holiday, so I'll check out the JavaFX preview release and see if the situation has improved.