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

JavaFX in the Wild: Sapphire!

12.18.2008
| 4885 views |
  • submit to reddit

With JavaFX 1.0 having been released just a few days ago, I'm pleased that we're observing more JavaFX applications "in the wild". Here's one that I became aware of recently, named Sapphire, developed by The Standards Company.

Picture 1


According to the website in which you can launch this JavaFX application:

"Sapphire is an advanced classroom observation tool. It provides an easy-to-use interface, multiple platform deployments, and interchangeable observation forms which can be customized to fit most any situation. The Community Edition [which is the version that you can try out from the link above] is a demonstration version requested by the Oklahoma State Department of Education and configured to complement the "Time on Task" observation form released in October 2008."

Some JavaFX Technical Notes from Ben Jones of The Standards Company: Real-time Charting in JavaFX

One of the features of JavaFX that makes it attractive to real-time application developers is its ability to tie graphical elements to models through the binding mechanism. This mechanism makes it possible for the current state of the model to be reflected in the interface without the need to create any type of polling system.

In our Sapphire application, we collect real-time data from classroom observations. The observer records classroom events by pressing various buttons. These events are displayed in several dashboard type displays which are actively tied to supporting models. One of these displays in a time lime of events created by a series of colored rectangles. The size, placement and color of the rectangles represent different relationships in the event data. Every time an event is pressed, the data changes and the bound display automatically updates.

To achieve this, you only need three things: a data model, a display element, and an event driver of some type. Let's take a look at one of the visual building blocks, the TimeOnTaskBlock class:


public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

public override function create(): Node {
return Group {

var maxDisplayHeight:Number = height/2;

content: [
Rectangle {
x: bind zoneWidth * startingMark / zoneSeconds;
y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
width: bind zoneWidth * seconds / zoneSeconds;
height: bind scale * (maxDisplayHeight * segment/maxSegments)
fill: bind aboveColor
strokeWidth:0
},
Rectangle {
x: bind zoneWidth * startingMark / zoneSeconds;
y: bind height / 2
width: bind zoneWidth * seconds / zoneSeconds;
height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
fill: bind belowColor
strokeWidth:0
}
]
effect: Lighting {
light: DistantLight { azimuth: 225 elevation: 60 }
surfaceScale: 2
}
};
}
}

This custom node represents what will be displayed. It is a pair of scaled rectangles stacked on top of each other. The various attributes define shape, size, and placement. Notice the use of the the DistantLight effect to give the rectangles in the graph some depth. The next building block up from this is another custom node that handles the visual orchestration of the time blocks nodes. The DisplayTimeChart node is effectively the dashboard element being displayed. It has a data member holding a sequence of TimeOnTaskBlock nodes. Let's take a peek at this node:


public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

public override function create(): Node {
return Group {

var maxDisplayHeight:Number = height/2;

content: [
Rectangle {
x: bind zoneWidth * startingMark / zoneSeconds;
y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
width: bind zoneWidth * seconds / zoneSeconds;
height: bind scale * (maxDisplayHeight * segment/maxSegments)
fill: bind aboveColor
strokeWidth:0
},
Rectangle {
x: bind zoneWidth * startingMark / zoneSeconds;
y: bind height / 2
width: bind zoneWidth * seconds / zoneSeconds;
height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
fill: bind belowColor
strokeWidth:0
}
]
effect: Lighting {
light: DistantLight { azimuth: 225 elevation: 60 }
surfaceScale: 2
}
};
}
}

 

The TimeDisplayChart serves a couple of purposes. First it builds the overall dashboard element. This defines the usual display space, necessary labeling and element placements. Please note two aspects of this class: the group where its content is bound to the displayBlocks sequence and the second group composed of a solo TimeOnTaskBlock. By binding the content of a group to a data source, any changes in the data source will be made available to the group automatically. This effectively produces a self-updating display since we bound a displayable node. The second group which is a single instance of the TimeOnTaskBlock serves another purpose. It covers the span of time since the last data change and the current time. Since the data model stores only past events, we need a means of showing data yet to be stored. It's real-time after all.

To place all of this into an application, an instance of TimeDisplayChart is placed into a group as follows:


Group {
translateY:310
translateX:10
content:[
TimeDisplayChart{
width:600
height:100
zoneSeconds:3600
zoneWidth:600
background:Color.#969696
timer: bind timer
displayTicker: bind displayTicker
currentSegment: bind appState.currentSegment
timeMark: bind appState.currentTimeMark
onColor: bind appState.onColor
offColor:bind appState.offColor
displayBlocks: bind displayblocks
}
]
}

Here we can see the various attributes of the custom node being bound to different data sources and conditions that exit within the larger context of the application. The bindings create an active communication channel between application state data and the graphical elements. It's convenient, responsive, and easy to manage during the development process.

JavaFX in the Enterprise

The technical notes that Ben Jones supplied above demonstrate that graphing real-time data is very achievable in JavaFX. This is one of the capabilities required by many enterprise applications, so I'd like to see an open source initiative that provides a library of JavaFX graphs (that have a contemporary RIA look and feel, of course).

Anyway, play with Sapphire, and please give The Standards Company your feedback on this very specialized JavaFX application. Also, if you have any JavaFX applications in the wild, please let me know at jim.weaver [at] javafxpert.com. At the moment I'm particularly interested in showcasing JavaFX apps that communicate with a server, such as enterprise applications and mashups.

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

Arek Stryjski replied on Thu, 2008/12/18 - 6:20am

If application start with the massage "Security Warning! The application's digital signature cannot be verified" probably it is correct to call it "in the wild".

I believe creators of JavaFX should do something about it otherwise soon it will be precieved by most people as something dangerous. This for sure will stop adoption of JavaFX as the technology used at public web sites.
Sun cannot blame developers of this application. I got it twice, second time for "JavaFX Runntime". Anyway if they give possibility to misuse something people will do it and it will affect whole technology.

Anyway the whole dialogs nightmare at WebStart application initialization is incredible. Can they read at Sun some book about usability?

PS
In the end  it didn't run at all :(
Probably because I'm on Linux. So if you use Windows they do all what possible to scare you. If you use secure OS and you can trust everybody it will not run.

What a great marketing strategy...

 

Lukas Krecan replied on Thu, 2008/12/18 - 10:20am in response to: Arek Stryjski

Hi, I've blogged about JavaFX security here.

Otengi Miloskov replied on Thu, 2008/12/18 - 12:11pm

In the beginning I was skeptical about JavaFX but lately I have playing a lot with it and let me tell you that is not a bad technology actually have a lot of potential and can be one of the best client API around right now. It just hit version 1.0, give it little time maybe at 1.1 and I think the pain will go away. It always happens with any software at version 1.0 have still lots of bugs and flaws but with little time it will get mature enough and it will be a great API, JavaFX can be it.

Mike P(Okidoky) replied on Thu, 2008/12/18 - 12:19pm

I agree that the security certificate thing is a HUGE problem.

From the blog that Lukas pointed out:
"the most secure choice is to write a JavaFX application that does not need any security permissions. If you do not sign it, it runs in the sandbox and everything is fine."

Client-server based software have the freedom to communicate back to the server where the application comes from. No need to get out of the sandbox.

What I do do sometimes, on my Linux box, is I have a script that creates a chroot environment, combined with unionfs. This is really neat. It's like having an instant playground area, where you restrict what exists inside that environment (eg. you leave our your home directory and give it a fresh one)., and where all the changes to the filesystem are stored as a layer in a temporary holding place. This way, even a malicious application can not see my private files, and any changes it makes, is discarded later. You can do this with standard Linux, with no additional software needed. You just need the right script that sets things up nicely.

Other than that, I never ever click those "go ahead I trust you" buttons. Unless it's something I'm installing, like Eclipse (if it were delivered that way - it's just an example). Seeing a security certificate popup should be considered broken software - a failure.

I'm disappointed that I can't see this "Saphire" application, because I refuse to give it my stamp of approval to see my box of underwear.

Comment viewing options

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