Original code by Christopher Oliver. Hour positions Group by Dean Iverson. See this thread in the mailing lists.
This is simple example of a clock that works in JFXPad.
Code[]
import javafx.ui.*;
import javafx.ui.canvas.*;
import java.util.Date;
import java.util.Math;
public class Timer {
private attribute elapsed: Number;
public attribute minutes: Number;
public attribute seconds: Number;
public attribute hours: Number;
public attribute running: Boolean;
}
attribute Timer.elapsed = bind if running
then [1..20] dur 1000 linear
while running
continue if true
else 0;
trigger on Timer.elapsed = value {
var now = new Date();
minutes = now.getMinutes();
seconds = now.getSeconds() + (now.getTime() % 1000)/1000;
hours = now.getHours();
}
public class Clock extends CompositeNode {
public attribute ticking: Boolean;
}
operation Clock.composeNode() {
var t = Timer {running: bind ticking};
return Group {
var font = new Font("Dialog", "PLAIN", 15)
var secs = bind t.seconds
var mins = bind t.minutes + secs/60
var hrs = bind t.hours + mins/60
content:
[Rect {
height: 200
width: 5000
fill: white
},
Circle {cx: 100, cy: 100, radius: 80, fill: blue, stroke: black, strokeWidth: 1},
Group {
transform: translate( 100, 100 )
content: foreach( i in [1..12] )
Text {
var radians = Math.toRadians( 30 * i - 90 )
transform: [translate( 70*Math.cos( radians ), 70*Math.sin( radians ) )]
content: "{i}"
valign: MIDDLE, halign: CENTER
}
},
Group {
transform: translate(100, 100)
var hourHand =
Line {x1: 0, y1: 0, x2: 0, y2: -35,
strokeWidth: 4, stroke: black
transform: bind rotate(hrs*30, 0, 0)
}
var minuteHand =
Line {x1: 0, y1: 0, x2: 0, y2: -55,
strokeWidth: 2, stroke: black,
transform: bind rotate(mins * 6, 0, 0)
}
var secondHand =
Line {x1: 0, y1: 0, x2: 0, y2: -75,
strokeWidth: 1, stroke: red,
transform: bind rotate(t.seconds * 6, 0, 0)
}
content: [hourHand, minuteHand, secondHand]
},
Circle {cx: 100, cy: 100, radius: 3, fill: black, stroke: black }]
};
}
Clock {ticking: true}
import javafx.ui.*; import javafx.ui.canvas.*; import java.util.Date; import java.util.Math; public class Timer { private attribute elapsed: Number; public attribute minutes: Number; public attribute seconds: Number; public attribute hours: Number; public attribute running: Boolean; } attribute Timer.elapsed = bind if running then [1..20] dur 1000 linear while running continue if true else 0; trigger on Timer.elapsed = value { var now = new Date(); minutes = now.getMinutes(); seconds = now.getSeconds() + (now.getTime() % 1000)/1000; hours = now.getHours(); } public class Clock extends CompositeNode { public attribute ticking: Boolean; } operation Clock.composeNode() { var t = Timer {running: bind ticking}; return Group { var font = new Font("Dialog", "PLAIN", 15) var secs = bind t.seconds var mins = bind t.minutes + secs/60 var hrs = bind t.hours + mins/60 content: [Rect { height: 200 width: 5000 fill: white }, Circle {cx: 100, cy: 100, radius: 80, fill: blue, stroke: black, strokeWidth: 1}, Group { transform: translate( 100, 100 ) content: foreach( i in [1..12] ) Text { var radians = Math.toRadians( 30 * i - 90 ) transform: [translate( 70*Math.cos( radians ), 70*Math.sin( radians ) )] content: "{i}" valign: MIDDLE, halign: CENTER } }, Group { transform: translate(100, 100) var hourHand = Line {x1: 0, y1: 0, x2: 0, y2: -35, strokeWidth: 4, stroke: black transform: bind rotate(hrs*30, 0, 0) } var minuteHand = Line {x1: 0, y1: 0, x2: 0, y2: -55, strokeWidth: 2, stroke: black, transform: bind rotate(mins * 6, 0, 0) } var secondHand = Line {x1: 0, y1: 0, x2: 0, y2: -75, strokeWidth: 1, stroke: red, transform: bind rotate(t.seconds * 6, 0, 0) } content: [hourHand, minuteHand, secondHand] }, Circle {cx: 100, cy: 100, radius: 3, fill: black, stroke: black }] }; } Clock {ticking: true}