Part Deux of Building a Calculator with the Shiny New JavaFX SDK 1.0
In the first post of this Simple Calculator App series, we took some baby steps toward creating a simple calculator. We're using the comp, shown below, that graphics designer Mark Dingman of Malden Labs supplied:
For teaching purposes, I'm taking a very incremental and sometimes indirect approach to building this. For example, in the first post I used the SwingButton class for the calculator keys. In this post, we'll use a Group that consists of a Rectangle and Text object to create each key. Also, we'll use a for expression to succinctly create the keys -- a technique that has another benefit related to event handling that you'll see in a moment. And remember, the calculator in its current state simply displays the keys typed rather than performing any calculations. We'll create that code when showing you how to define classes, functions, etc. in JavaFX.
Click on the calculator image above to invoke the Simple Calculator JavaFX applet, or the Java Web Start icon below to make the application appear in its own window:
Understanding the Code Behind this JavaFX Applet
Take a look at the code below, and note what has changed since its first incarnation.
/*
* SimpleCalc2.fx
*
* Developed 2008 by James L. Weaver (jim.weaver at javafxpert.com)
* to demonstrate creating applications using JavaFX SDK 1.0
*/
package javafxpert;
import javafx.ext.swing.*;
import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.scene.transform.*;
/**
* The "stage" for the application
*/
Stage {
// The model
var displayStr:String;
var keyLabels = ["7", "8", "9", "+",
"4", "5", "6", "-",
"1", "2", "3", "x",
"0", ".", "=", "/"];
title: "Calculator 2"
scene: Scene {
// The gradient on the calculator keys
var btnGradient = LinearGradient {
startX: 0.0, startY: 0.0,
endX: 0.0, endY: 1.0
stops: [
Stop {
offset: 0.0
color: Color.rgb(166, 166, 168)
},
Stop {
offset: 1.0
color: Color.rgb(122, 122, 122)
}
]
};
content: [
// The rounded rectangle behind the entire calculator
Rectangle {
width: 278
height: 401
arcWidth: 16
arcHeight: 16
fill: LinearGradient {
startX: 0.0, startY: 0.0,
endX: 0.5, endY: 1.0
stops: [
Stop {
offset: 0.0
color: Color.rgb(119, 116, 123)
},
Stop {
offset: 1.0
color: Color.rgb(2, 2, 2)
}
]
},
},
VBox {
transforms: bind Translate.translate(20, 20)
spacing: 27
content: [
// The calculator's display
TextBox {
text: bind displayStr
width: 238
height: 65
editable: false
style: bind "text-fill: #343434; "
"background-fill: #f4f4f4; "
"font: 28pt Dialog; "
"font-weight: bold; "
},
// The calculator's keys
VBox {
spacing: 2
content: for (row in [0..3]) {
HBox {
spacing: 2
content: for (column in [0..3]) {
Group {
var rectRef:Rectangle;
var textRef:Text;
content: [
rectRef = Rectangle {
width: 58
height: 50
fill: btnGradient
},
textRef = Text {
transforms: bind
Translate.translate((rectRef.layoutBounds.width -
textRef.layoutBounds.width) / 2,
(rectRef.layoutBounds.height -
textRef.layoutBounds.height) / 2)
content: keyLabels[row * 4 + column]
textOrigin: TextOrigin.TOP
fill: Color.rgb(222, 222, 222)
font: Font {
name: "Arial Bold"
size: 30
}
}
]
onMouseClicked: function(me:MouseEvent):Void {
displayStr = "{displayStr}{textRef.content}"
}
}
}
}
}
}
]
}
]
}
}Notice the for expressions that creates an HBox for each row, and a Group for each calculator key in a row. The value of a for expression is a sequence (think array) of objects. More information on the for expression can be found in the JavaFX Language Reference (in development at this writing).
Another noteworthy item is the value of the transforms attribute in the Text object. The Translate.translate function above causes the Text to be centered horizonally and vertically within the Rectangle.
One of the advantages of using the for expression is that only one event handler is required for all of the keys, rather than one for each key as in the previous Simple Calculator version. In this case the onMouseClicked attribute is on the Group that contains the Rectangle and Text.
One more item of note is the use of the LinearGradient class to make the application begin looking more like the graphic comp shown above. Consult the JavaFX API docs for more information on using this class. By the way, the API documentation is available online as well as being in the JavaFX SDK.
Please leave a comment if you have any questions!
Regards,
Jim Weaver
JavaFXpert.com
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Osvaldo Doederlein replied on Thu, 2008/12/11 - 9:11am
Carl Dea replied on Thu, 2008/12/11 - 9:52am
Jim,
How did you get Mark Dingman's calculator turned in to code in the example above?
I'm sure the designer made the buttons, but putting them into the for/sequence loops was done by you.
I'm just trying to understand the workflow (getting from Mark to You).
It almost seems like either Mark knows fx programming or you knew about design widgets (svg, fxd, etc.).
-Carl
Richard Osbaldeston replied on Thu, 2008/12/11 - 11:10am
in response to:
Osvaldo Doederlein
Osvaldo Doederlein replied on Thu, 2008/12/11 - 1:10pm
in response to:
Richard Osbaldeston
[quote=osbald]That's just the way JavaFX works I think, being a high level language you don't see all the messy details. JavaFX bindings use reflection no doubt, and there's lots of calls in & out of native code for the flashy bits and media codecs - all of which won't be allowed by the untrusted sandbox for very good reasons.[/quote]
This is only justifiable, perhaps, if (because?) JavaFX is considered an untrusted package by the JavaPlugIn. ANY Java application uses a good chunk of native code: the JVM itself, native parts of IO, AWT, networking, etc. These DLLs come with the JRE and are trusted. But JavaFX applets depend on DLLs that they install on demand in the JRE's cache. This installation should happen without any manual security validation, because FX is made by Sun and they can digitally sign the whole thing with Sun's super powerful certificate, so the JRE should trust it automatically.
Reflection is not a problem, any untrusted Java code can use reflection, just not into private parts of core classes.
Richard Osbaldeston replied on Thu, 2008/12/11 - 1:29pm
in response to:
Osvaldo Doederlein
Jim Weaver replied on Thu, 2008/12/11 - 1:40pm
in response to:
Carl Dea
Carl,
Mark Dingman is not a programmer and I'm *definitely* not a graphics designer. :-)
So far, in this series, I've been working only from Mark Dingman's comp, not using any assets yet. Knowing the gradient colors, etc, makes it easy to duplicate in JavaFX. I may use some graphical assets for the numbers on the buttons, and if so, Mark will supply them as an FXZ file from from Photoshop with the JavaFX 1.0 Production Suite plugin (AKA Project Nile). The FXZ file is a zipped file that contains an FXD file that contains JavaFX declarative script to define the graphics, as well as assets such as images and font definitions.
Thanks,
Jim Weaver
JavaFXpert.com
Jim Weaver replied on Thu, 2008/12/11 - 6:33pm
in response to:
Osvaldo Doederlein
I asked Josh Marinacci of Sun this question to make sure that I give you an accurate answer. Here is Josh's response:
In addtion, I did (unnecessarily) sign the FX application, so that explains the other security dialog. I'm going to remove the signature because this applet doesn't need to play outside the sandbox.
Thanks,
Jim Weaver
Richard Osbaldeston replied on Fri, 2008/12/12 - 10:10am
in response to:
Jim Weaver
Jim Weaver replied on Fri, 2008/12/12 - 1:08pm
in response to:
Richard Osbaldeston
Richard,
An old Saturday Night Live quote by the late Gilda Radner comes to mind: "My father would tuck me in my little bed and say, 'Rosanna Rosannadanna, it's always something.'" :-)
Thanks,
Jim Weaver