What's the best way to update the JavaFX2 gui for high speed operations?
I have an application that talks to a hardware device over a serial port. This device sends a json object every 30ms. This json object is the devices that "define" their motion controller.
Basically, the messages look like this:
{"sr":{"line":2524,"posx":1.000,"posy":21.000,"posz":20.000,"posa":11.459,"feed":0.000,"vel":0.000,"unit":1,"coor":1,"dist":0,"frmo":0,"momo":0,"stat":2}}
I get these 1x every 30ms. I have to take them apart. Then "draw" them in the JavaFX GUI.
This is how I figure it out:
Platform.runLater(new Runnable() {
public void run() {
//We are now back in the EventThread and can update the GUI
try {
JsonRootNode json = JDOM.parse(l);
xAxisVal.setText(json.getNode("sr").getNode("posx").getText());
yAxisVal.setText(json.getNode("sr").getNode("posy").getText());
zAxisVal.setText(json.getNode("sr").getNode("posz").getText());
aAxisVal.setText(json.getNode("sr").getNode("posa").getText());
drawLine();
} catch (argo.saj.InvalidSyntaxException ex) {
//Json line invalid.
}
}
});
And here is the drawing code I am using:
public void drawLine() {
xl.setX(Float.parseFloat(xAxisVal.getText()) + 400);
y1.setY(Float.parseFloat(yAxisVal.getText()) + 400);
LineTo tmpL = new LineTo((Float.parseFloat(xAxisVal.getText()) * 2) + 400, (Float.parseFloat(yAxisVal.getText()) * 2) + 400);
path.getElements().add(tmpL);
}
So basically I create an executable every 30ms and then parsing and drawing. Is this the best way to do it? You can see the video in action:
http://www.youtube.com/watch?v=dhBB3QcmHOg&feature=youtu.be
But this is similar to his "abrupt" and rather resource hunger. I hope someone gives me suggestions for optimizing this code? Possibly point out something I'm missing?
As a FYI, the motion controller board we are creating is called TinyG. Its hardware is open source.
More information here:
http://www.synthetos.com/wiki/index.php?title=Projects:TinyG
The firmware is here: https://github.com/synthetos/TinyG
Thank!
source to share
You seem to be doing too much computation in the event queue, which is blocking graphics rendering when your data is parsed. You have to do the calculations in a separate thread and Platform.runLater()
only call for the corresponding ui code:
try {
JsonRootNode json = JDOM.parse(l);
final String xVal = json.getNode("sr").getNode("posx").getText();
final String yVal = json.getNode("sr").getNode("posy").getText();
final String zVal = json.getNode("sr").getNode("posz").getText();
final String aVal = json.getNode("sr").getNode("posa").getText();
// here you are calling UI getter, and parse it each time
// it would be more optimal to store `x` value in separate variable
// between updates
final float x = Float.parseFloat(xAxisVal.getText());
final float y = Float.parseFloat(yAxisVal.getText());
Platform.runLater(new Runnable() {
public void run() {
//We are now back in the EventThread and can update the GUI
try {
xAxisVal.setText(xVal);
yAxisVal.setText(yVal);
zAxisVal.setText(zVal);
aAxisVal.setText(aVal);
xl.setX(x + 400);
y1.setY(y + 400);
LineTo tmpL = new LineTo(x * 2 + 400, y * 2 + 400);
path.getElements().add(tmpL);
}
}
}
} catch (argo.saj.InvalidSyntaxException ex) {
//Json line invalid.
}
source to share
If you haven't already, try the developer preview . In the JavaFX 2.1 preview thread, some changes have been made to smooth animation and rendering performance, and path logic has been optimized .
Alternative approaches would be writing to an HTML5 canvas in a WebView, or using the JavaFX canvas node if available in JavaFX 2.2.
source to share