All the Interesting ThingsThis is a personal web log. All information posted here does not represent my employer. I do not speak for my employer. |
|
Sunday Jun 21, 2009
Pure Java Code to Invoke JavaFX Charting Features
From time to time, people asked questions like "how to call JavaFX from Java code?". After the release of JavaFX 1.0, I wrote a
post Interoperability between JavaFX and Java. I discussed three possible approaches to invoke JavaFX features from the Java side. These approaches were:
The third one seems the most elegant way to call JavaFX from Java. However, there is a drawback: the program should start from the JavaFX side. The reason is that it is simpler to use JavaFX code to instantiate the JavaFX classes which can be passed to Java code. Nevertheless, in some scenario, it would be better to start the program from the java side. For example, if you want to add in some JavaFX features to an existing large java application, it is better to have java code as the entry point. To solve this issue, I would introduce an approach for Pure Java Code to Call JavaFX Class. In fact, I am combining the essence of Approach 2 and 3 to create the below example. Let's say we want to invoke the latest charting functions of JavaFX 1.2 from the java code. We will first use the JavaFX reflection API to instantiate the JavaFX class. We then use it via its java interface. So we define a Java interface first.
/*
* JavaInterface.java
*
* @author Henry Zhang http://www.javafxgame.com
*/
package javatest;
public interface JavaInterface {
public void addData(String name, float data);
public void showChart();
}
The next step is to create a JavaFX class MyChart to implements this interface:
/*
* MyChart.fx
*
* @author Henry Zhang http://www.javafxgame.com
*/
package javatest;
import javafx.scene.chart.PieChart;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.chart.PieChart3D;
public class MyChart extends JavaInterface {
var chartData : PieChart.Data[] = [];
public override function addData( l:String, v: Number):Void {
var labelString = l;
var data = PieChart.Data {
label : l
value : v
action: function() {
println("{labelString} clicked!");
}
} ;
insert data into chartData;
}
public override function showChart() : Void {
var chart =
PieChart3D {
data : chartData
pieThickness: 25
pieLabelFont: Font{ size: 9 };
pieToLabelLineOneLength: 10
pieToLabelLineTwoLength : 20
pieLabelVisible: true
pieValueVisible: true
translateY: -50
};
Stage {
title: "PieChart Window"
width: 520
height: 300
scene: Scene {
content: [
Text {
font : Font {
size : 16
}
x: 200
y: 20
content: "Pie Chart"
},
chart
]
}
}
}
}
The last thing is to write the java main class JavaTest.
/*
* JavaTest.java
* @author Henry Zhang http://www.javafxgame.com
*/
package javatest;
import javafx.reflect.FXClassType;
import javafx.reflect.FXLocal;
import javafx.reflect.FXLocal.Context;
import javafx.reflect.FXLocal.ObjectValue;
public class JavaTest {
public static void main(String args[]) {
Context context = FXLocal.getContext();
FXClassType instance = context.findClass("javatest.MyChart");
ObjectValue obj = (ObjectValue)instance.newInstance();
JavaInterface ji = (JavaInterface)obj.asObject();
String [] labels = {"January", "Febuary", "March", "April"};
int [] values = { 18, 20, 25, 37 };
for ( int i=0; i < values.length; i++ ) {
ji.addData(labels[i], values[i]);
}
ji.showChart();
}
}
In the above code, there are three lines for instantiating a JavaFX class via reflection:
Context context = FXLocal.getContext();
FXClassType instance = context.findClass("javatest.MyChart");
ObjectValue obj = (ObjectValue)instance.newInstance();
The next line is to convert the JavaFX instance into a java interface so that it can be used by Java code:
JavaInterface ji = (JavaInterface)obj.asObject();
If you are using NetBeans IDE, you can set javatest.JavaTest as the main class in your project properties(so that it can be the entry point of your program). Build this project you will get a javatest.jar. Running this program produces the below screenshot:
To run it from the command line, use the below command: javafx -jar javatest.jar Actually, you could do it in the purest java style by including all the JavaFX runtime stuffs, the command would look like this:
java -Djava.library.path="<path to javafx sdk lib>"
-classpath "<all javafx sdk jars>" -jar javatest.jar
Since there are many jar files used by the JavaFX, this purest java approach turns out to be very troublesome. I would rather use the javafx command, which is a wrapper of the above java command.
Please leave comments if you have any questions. Posted at 08:14PM Jun 21, 2009 by morningstar in JavaFX | Comments[8] |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Nice one !
Posted by Vaibhav Choudhary on June 21, 2009 at 10:12 PM PDT #
Cool ! Thanks for sharing this !
Any chance to include JavaFX in a Swing based application ?
What about the posisbility to include a PieChart in a JPanel for example ?
Posted by Sebastien Stormacq on June 21, 2009 at 10:49 PM PDT #
I think the JavaFX controls cannot be used with SWING controls together. At least you need some conversion code to mix these two things together. Maybe I will give it a try some time later.
Posted by Hai-Ning Henry Zhang on June 21, 2009 at 11:05 PM PDT #
@Hai-Ning Henry Zhang there is the SGPanel that still live in JavaFX 1.2 that can integrate scene graphs as swing components, but the documentation (and commitment to not break it in 1.3) is very lacking.
Posted by Danno Ferrin on June 22, 2009 at 09:14 AM PDT #
What I don't like about this approach java to javafx interop is that this requires three different and distinct compile steps! (a) create the interface in Java, (b) create the code in JavaFX and (c) create the executable in java.
This looks to be a general problem, because there is still no quality way to use the JavaFX Stack with out using JavaFX Script. Getting some jars and DLLs into a coprate build system isn't terribly hard for new technology. Getting a new language syntax? You better have executive level support or the ability to move heaven and earth.
Posted by Danno Ferrin on June 22, 2009 at 09:16 AM PDT #
You can find more information on how to mix javafx and swing here: http://weblogs.java.net/blog/aim/archive/2009/06/insiders_guide.html
Posted by Dmitri Trembovetski on June 22, 2009 at 03:37 PM PDT #
@Danno : This article refers to Swing embedded in a JavaFX app. I am looking for the other way around
Posted by Sebastien Stormacq on June 22, 2009 at 10:17 PM PDT #
@Sebastien Stormacq Stephen Chin's JFXtras project provides a class to put JavaFX Scence into a JComponent. However, this approach uses internal JavaFX api, it may break in the future release. Check it out here:
http://steveonjava.com/2009/06/22/jfxtras-0-5-release-announcement/
@Danno The code only needs 1 round of compilation. You just build your original Java project as a JavaFX project.
Posted by Hai-Ning Henry Zhang on June 22, 2009 at 10:47 PM PDT #