blob: 0b39118f7e5f56584aff0315d5fd09a986eef02c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package digitalclock;
import java.util.Calendar;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.effect.Effect;
import javafx.scene.effect.Glow;
import javafx.scene.effect.InnerShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Shear;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* A digital clock application that demonstrates JavaFX animation, images, and
* effects.
*
* @see javafx.scene.effect.Glow
* @see javafx.scene.shape.Polygon
* @see javafx.scene.transform.Shear
* @resource DigitalClock-background.png
*/
public class DigitalClock extends Application {
private Clock clock;
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Digital Clock");
Group root = new Group();
Scene scene = new Scene(root, 480, 412);
// add background image
ImageView background = new ImageView(new Image(getClass().getResourceAsStream("DigitalClock-background.png")));
// add digital clock
clock = new Clock(Color.ORANGERED, Color.rgb(50,50,50));
clock.setLayoutX(45);
clock.setLayoutY(186);
clock.getTransforms().add(new Scale(0.83f, 0.83f, 0, 0));
// add background and clock to sample
root.getChildren().addAll(background, clock);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Clock made of 6 of the Digit classes for hours, minutes and seconds.
*/
public static class Clock extends Parent {
private Calendar calendar = Calendar.getInstance();
private Digit[] digits;
private Timeline delayTimeline, secondTimeline;
public Clock(Color onColor, Color offColor) {
// create effect for on LEDs
Glow onEffect = new Glow(1.7f);
onEffect.setInput(new InnerShadow());
// create effect for on dot LEDs
Glow onDotEffect = new Glow(1.7f);
onDotEffect.setInput(new InnerShadow(5,Color.BLACK));
// create effect for off LEDs
InnerShadow offEffect = new InnerShadow();
// create digits
digits = new Digit[7];
for (int i = 0; i < 6; i++) {
Digit digit = new Digit(onColor, offColor, onEffect, offEffect);
digit.setLayoutX(i * 80 + ((i + 1) % 2) * 20);
digits[i] = digit;
getChildren().add(digit);
}
// create dots
Group dots = new Group(
new Circle(80 + 54 + 20, 44, 6, onColor),
new Circle(80 + 54 + 17, 64, 6, onColor),
new Circle((80 * 3) + 54 + 20, 44, 6, onColor),
new Circle((80 * 3) + 54 + 17, 64, 6, onColor));
dots.setEffect(onDotEffect);
getChildren().add(dots);
// update digits to current time and start timer to update every second
refreshClocks();
play();
}
private void refreshClocks() {
calendar.setTimeInMillis(System.currentTimeMillis());
int hours = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
digits[0].showNumber(hours / 10);
digits[1].showNumber(hours % 10);
digits[2].showNumber(minutes / 10);
digits[3].showNumber(minutes % 10);
digits[4].showNumber(seconds / 10);
digits[5].showNumber(seconds % 10);
}
public void play() {
// wait till start of next second then start a timeline to call refreshClocks() every second
delayTimeline = new Timeline();
delayTimeline.getKeyFrames().add(
new KeyFrame(new Duration(1000 - (System.currentTimeMillis() % 1000)), new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
if (secondTimeline != null) {
secondTimeline.stop();
}
secondTimeline = new Timeline();
secondTimeline.setCycleCount(Timeline.INDEFINITE);
secondTimeline.getKeyFrames().add(
new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
refreshClocks();
}
}));
secondTimeline.play();
}
})
);
delayTimeline.play();
}
public void stop(){
delayTimeline.stop();
if (secondTimeline != null) {
secondTimeline.stop();
}
}
}
/**
* Simple 7 segment LED style digit. It supports the numbers 0 through 9.
*/
public static final class Digit extends Parent {
private static final boolean[][] DIGIT_COMBINATIONS = new boolean[][]{
new boolean[]{true, false, true, true, true, true, true},
new boolean[]{false, false, false, false, true, false, true},
new boolean[]{true, true, true, false, true, true, false},
new boolean[]{true, true, true, false, true, false, true},
new boolean[]{false, true, false, true, true, false, true},
new boolean[]{true, true, true, true, false, false, true},
new boolean[]{true, true, true, true, false, true, true},
new boolean[]{true, false, false, false, true, false, true},
new boolean[]{true, true, true, true, true, true, true},
new boolean[]{true, true, true, true, true, false, true}};
private final Polygon[] polygons = new Polygon[]{
new Polygon(2, 0, 52, 0, 42, 10, 12, 10),
new Polygon(12, 49, 42, 49, 52, 54, 42, 59, 12f, 59f, 2f, 54f),
new Polygon(12, 98, 42, 98, 52, 108, 2, 108),
new Polygon(0, 2, 10, 12, 10, 47, 0, 52),
new Polygon(44, 12, 54, 2, 54, 52, 44, 47),
new Polygon(0, 56, 10, 61, 10, 96, 0, 106),
new Polygon(44, 61, 54, 56, 54, 106, 44, 96)};
private final Color onColor;
private final Color offColor;
private final Effect onEffect;
private final Effect offEffect;
public Digit(Color onColor, Color offColor, Effect onEffect, Effect offEffect) {
this.onColor = onColor;
this.offColor = offColor;
this.onEffect = onEffect;
this.offEffect = offEffect;
getChildren().addAll(polygons);
getTransforms().add(new Shear(-0.1,0));
showNumber(0);
}
public void showNumber(Integer num) {
if (num < 0 || num > 9) num = 0; // default to 0 for non-valid numbers
for (int i = 0; i < 7; i++) {
polygons[i].setFill(DIGIT_COMBINATIONS[num][i] ? onColor : offColor);
polygons[i].setEffect(DIGIT_COMBINATIONS[num][i] ? onEffect : offEffect);
}
}
}
/**
* The main() method is ignored in correctly deployed JavaFX
* application. main() serves only as fallback in case the
* application can not be launched through deployment artifacts,
* e.g., in IDEs with limited FX support. NetBeans ignores main().
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}