I had great fun entering the JFXStudio challenge to write a time themed JFX application in less than 30 lines or 3000 characters. Here is my entry a radial clock made of words:

Click to run "Radial Word Clock"

Click to run "Radial Word Clock"

Unfortunatly I did not win you can see the winner and other great entries at JFXStudio challenge “Time” winner announced. My favorite entry is Spin Clock by Stephen Chin. I have to admit I the idea for mine from a Mac Screensaver that I liked. Here is the code for it if you want to try it out your self.

[jfx]
import javafx.stage.Stage; import javafx.scene.*; import javafx.scene.transform.*;
import javafx.scene.text.*; import javafx.scene.paint.*; import javafx.animation.*;
import java.util.Calendar;
def font = Font{size:12};
def numbers = ["twelve","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve",
"thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"];
def tens = ["","","twenty","thirty","forty","fifty"];
var hRot:Number;var mRot:Number;var sRot:Number;var mOffset:Number;var sOffset:Number;
def hours = for (h in [0..11]) Text { transforms: [Rotate{angle: bind hRot+((360/12)*h)},Translate{x:80}] fill:Color.WHITE font: font content:numbers[h] };
def minutes = for (m in [0..59]) Text { transforms: [Rotate{angle: bind mRot+((360/60)*m)},Translate{x:bind mOffset+80}] fill:Color.WHITE font: font content: if(m==0) "o’clock" else if (m<10) "oh-{numbers[m]}" else if (m<20) numbers[m] else "{tens[(m/10)]}{if(m mod 10==0)""else "-{numbers[m mod 10]}"}"};
def seconds = for (s in [0..59]) Text { transforms: [Rotate{angle: bind sRot+((360/60)*s)},Translate{x:bind sOffset+80}] fill:Color.WHITE font: font content: if(s==0) "precisely" else if (s<20) numbers[s] else "{tens[(s/10)]}{if(s mod 10==0)""else "-{numbers[s mod 10]}"}"};
def andT = Text{ font: font, fill: Color.RED, content: "and"};
def secondsT = Text{ font: font, fill: Color.RED, content: bind if (c.get(c.SECOND)==0) then "second" else "seconds"};
var c:Calendar;
Stage { scene:Scene {fill:Color.BLACK width: 800,height: 800 content: Group{translateX: 400 translateY: 400 content:[hours,minutes,seconds,andT,secondsT]}}}
Timeline { repeatCount: Timeline.INDEFINITE, keyFrames: KeyFrame{ time: 1s, action: function(){
var nc = Calendar.getInstance();
if (c.get(c.HOUR)!=nc.get(c.HOUR)) Timeline { keyFrames: at(200ms) {hours[c.get(c.HOUR)].fill => Color.WHITE;hours[nc.get(c.HOUR)].fill => Color.RED}}.play();
if (c.get(c.MINUTE)!=nc.get(c.MINUTE)) Timeline { keyFrames: at(200ms) {minutes[c.get(c.MINUTE)].fill => Color.WHITE;minutes[nc.get(c.MINUTE)].fill => Color.RED}}.play();
Timeline { keyFrames: at(200ms) {
hRot => 360-((360/12) *nc.get(c.HOUR));mRot => 360-((360/60) *nc.get(c.MINUTE));sRot => 360-((360/60) *nc.get(c.SECOND));
seconds[nc.get(c.SECOND)].fill => Color.RED;seconds[c.get(c.SECOND)].fill => Color.WHITE;
mOffset => hours[nc.get(c.HOUR)].layoutBounds.width + 5;
andT.translateX => hours[nc.get(c.HOUR)].layoutBounds.width + minutes[nc.get(c.MINUTE)].layoutBounds.width + 85;
sOffset => hours[nc.get(c.HOUR)].layoutBounds.width + andT.layoutBounds.width + minutes[nc.get(c.MINUTE)].layoutBounds.width + 5;
secondsT.translateX => hours[nc.get(c.HOUR)].layoutBounds.width + andT.layoutBounds.width + minutes[nc.get(c.MINUTE)].layoutBounds.width + seconds[nc.get(c.SECOND)].layoutBounds.width + 85
} }.play();
c = nc;
}} }.play();
[/jfx]