Jim has posted 66 posts at DZone. You can read more from them at their website. View Full User Profile

Part Deux of Building a Calculator with the Shiny New JavaFX SDK 1.0

12.11.2008
| 6006 views |
  • submit to reddit

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:

Calculator_comp

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:

Webstart.small2

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

Published at DZone with permission of its author, Jim Weaver.

(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

Why should this applet show a security dialog? I guess it's not doing anything security critical...

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

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.

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

It's hard to know for sure without getting a peak at the code, everything else is guesswork. Is there implicit/automatic trust? I thought web start liked to ask even for trusted certs.

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

Why should this applet show a security dialog? I guess it's not doing anything security critical... 

I asked Josh Marinacci of Sun this question to make sure that I give you an accurate answer.  Here is Josh's response:

The JavaFX runtime itself must be signed because of everything it accesses, but the FX applications don't need to be signed unless they are doing something that requires them to get outside the sandbox. You should only see the security dialog for the FX runtime once. After that it will be cached. Sometimes in pre-J6u10 JREs the FX runtime isn't cached well and is downloaded again, triggering the dialog again. If you are seeing this behavior in 6u10 and above then it's a serious bug we must fix.

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

Course now it's unsigned people are going to be asking why is there a weird little floating warning sign next to my calc app?! The warnings a bit less in-your-face than it used to be, but far less obvious to users who'd could easily fall for a spoof attack with such a de-emphasized cue.

Jim Weaver replied on Fri, 2008/12/12 - 1:08pm in response to: Richard Osbaldeston

Course now it's unsigned people are going to be asking why is there a weird little floating warning sign next to my calc app?!

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

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.