package clock; import java.util.Calendar; import javafx.animation.Animation; import javafx.animation.Interpolator; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.beans.property.DoubleProperty; import javafx.scene.Group; import javafx.scene.control.Label; import javafx.scene.shape.Circle; import javafx.scene.shape.Line; import javafx.scene.transform.Rotate; import javafx.util.Duration; /** * Displays an animated AnalogueClock face. * Time is the system time for the local timezone. * see: analogue-clock.css for css formatting rules for the clock. */ public class AnalogueClock extends Group { final int HOUR_HAND_LENGTH = 50; final int MINUTE_HAND_LENGTH = 75; final int SECOND_HAND_LENGTH = 88; final int SECOND_HAND_OFFSET = 15; AnalogueClock(String brandName, double clockRadius) { setId("analogueClock"); getStylesheets().add( ResourceResolver.getResourceFor( getClass(), "analogue-clock.css" ) ); // construct the analogueClock pieces. final Circle face = createClockFace(clockRadius); //钟表面 final Label brand = createBrand(face, brandName); //钟表名 final Line hourHand = createHand( //钟时指针 "hourHand", clockRadius, 0, percentOf(HOUR_HAND_LENGTH, clockRadius) ); final Line minuteHand = createHand( //钟分指针 "minuteHand", clockRadius, 0, percentOf(MINUTE_HAND_LENGTH, clockRadius) ); final Line secondHand = createHand( //钟秒指针 "secondHand", clockRadius, percentOf(SECOND_HAND_OFFSET, clockRadius), percentOf(SECOND_HAND_LENGTH, clockRadius) ); // animate the hands with the time. bindClockHandsToTime(hourHand, minuteHand, secondHand); getChildren().addAll( face, brand, createTicks(clockRadius), createSpindle(clockRadius), hourHand, minuteHand, secondHand ); } //创建12条时间线 /** @return radial ticks around the clock center to mark time. */ private Group createTicks(double clockRadius) { final double TICK_START_OFFSET = percentOf(83, clockRadius); final double TICK_END_OFFSET = percentOf(93, clockRadius); final Group ticks = new Group(); for (int i = 0; i < 12; i++) { Line tick = new Line(0, -TICK_START_OFFSET, 0, -TICK_END_OFFSET); tick.getStyleClass().add("tick"); tick.setLayoutX(clockRadius); tick.setLayoutY(clockRadius); tick.getTransforms().add(new Rotate(i * (360 / 12))); ticks.getChildren().add(tick); } return ticks; } //创建中心点 /** @return a rendered spindle around which the clockwork rotates */ private Circle createSpindle(double clockRadius) { final Circle spindle = new Circle(clockRadius, clockRadius, 5); spindle.setId("spindle"); return spindle; } //创建圆 private Circle createClockFace(double clockRadius) { final Circle face = new Circle(clockRadius, clockRadius, clockRadius); face.setId("face"); return face; } //创建时,分,秒钟指针 private Line createHand(String handId, double clockRadius, double handOffsetLength, double handLength) { final Line secondHand = new Line(0, handOffsetLength, 0, -handLength); secondHand.setLayoutX(clockRadius); secondHand.setLayoutY(clockRadius); secondHand.setId(handId); return secondHand; } //创建名字 private Label createBrand(Circle face, String brandName) { final Label brand = new Label(brandName); brand.setId("brand"); brand.layoutXProperty().bind(face.centerXProperty().subtract(brand.widthProperty().divide(2))); brand.layoutYProperty().bind(face.centerYProperty().add(face.radiusProperty().divide(2))); return brand; } //绑定时间 private void bindClockHandsToTime(final Line hourHand, final Line minuteHand, final Line secondHand) { // determine initial rotation for the clock hands. Calendar time = Calendar.getInstance(); final double initialHourhandDegrees = calculateHourHandDegrees(time); final double initialMinuteHandDegrees = calculateMinuteHandDegrees(time); final double initialSecondHandDegrees = calculateSecondHandDegrees(time); // animate the clock movements using timelines. createRotationTimeline( // the hour hand rotates twice a day. createRotate(hourHand, initialHourhandDegrees).angleProperty(), //创建一个Rotate,并获取角度属性 Duration.hours(12), initialHourhandDegrees ); createRotationTimeline( // the minute hand rotates once an hour. createRotate(minuteHand, initialMinuteHandDegrees).angleProperty(), Duration.minutes(60), initialMinuteHandDegrees ); createRotationTimeline( // move second hand rotates once a minute. createRotate(secondHand, initialSecondHandDegrees).angleProperty(), Duration.seconds(60), initialSecondHandDegrees ); } private Rotate createRotate(Line hand, double initialHandDegrees) { final Rotate hourRotate = new Rotate(initialHandDegrees); hand.getTransforms().add(hourRotate); return hourRotate; } /** * Performs a 360 degree rotation of the angleProperty once in every duration. * rotation starts from initialRotation degrees. */ private void createRotationTimeline(DoubleProperty angleProperty, Duration duration, double initialRotation) { Timeline timeline = new Timeline( new KeyFrame( duration, new KeyValue( angleProperty, 360 + initialRotation, Interpolator.LINEAR ) //转一圈 ) ); timeline.setCycleCount(Animation.INDEFINITE); timeline.play(); } //获取当前秒占多少度(1秒占360/60度) private int calculateSecondHandDegrees(Calendar time) { System.out.println(time.get(Calendar.SECOND) * (360 / 60)); return time.get(Calendar.SECOND) * (360 / 60); } private double calculateMinuteHandDegrees(Calendar time) { return (time.get(Calendar.MINUTE) + calculateSecondHandDegrees(time) / 360.0) * (360 / 60); } private double calculateHourHandDegrees(Calendar time) { return (time.get(Calendar.HOUR) + calculateMinuteHandDegrees(time) / 360.0) * (360 / 12); } private double percentOf(double percent, double clockRadius) { return percent / 100 * clockRadius; } public static void main(String args[]){ Calendar calendar = Calendar.getInstance(); } }
主要是该类实现时钟
其中,关于line的移动疑惑了好久,为什么围绕着中心点转,自己弄了个例子调试了下,原来line是围绕着layoutX,layoutY转,上面设置了line的layoutX,layoutY为中心点,所以就围绕着中心点转。
其主要就是给line添加一个rotate,然后rotate的angerProperty一直变化。
这里有个javafx学习的中文网站,我把内容都丢那上面去了。
http://www.jfxee.com/