先看效果图:
package com.example.w9;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class NewClockPane extends Pane {
private int hour;
private int minute;
private int second;
private Line[] linesList = new Line[60];
private Text[] textsList = new Text[12];
public NewClockPane(){
setCurrentTime();
}
public NewClockPane(int hour, int minute, int second){
this.hour = hour;
this.minute = minute;
this.second = second;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
public void setCurrentTime(){
Calendar calendar = new GregorianCalendar();
this.hour = calendar.get(Calendar.HOUR_OF_DAY);
this.minute = calendar.get(Calendar.MINUTE);
this.second = calendar.get(Calendar.SECOND);
paintClock();
}
private void paintClock(){
double clockRadius = Math.min(getWidth(), getHeight()) * 0.8 * 0.5;
double centerX = getWidth() / 2; //继承父类Pane的方法, 保证时钟居中
double centerY = getHeight() / 2;
Circle circle = new Circle(centerX, centerY, clockRadius);
circle.setFill(Color.rgb(240,247,201));
circle.setStroke(Color.rgb(254,16,94));
circle.setStrokeWidth(5);
for (int i = 0; i < this.linesList.length; i++){
if (i == 0){
// double angle = Math.PI / 2 - i * Math.PI / 30;
Line line = new Line(
centerX + 0.85 * clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - 0.85 * clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30),
centerX + clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30));
line.setStroke(Color.rgb(254,16,94));
this.linesList[i] = line;
int num = i / 5;
Text text = new Text(centerX +0.8 * clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - 0.8 * clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30),
12 +"");
this.textsList[num] = text;
}
if (i % 5 == 0 && i != 0){
// double angle = Math.PI / 2 - i * Math.PI / 30;
Line line = new Line(
centerX + 0.85 * clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - 0.85 * clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30),
centerX + clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30));
line.setStroke(Color.rgb(254,16,94));
this.linesList[i] = line;
int num = i / 5;
Text text = new Text(centerX +0.8 * clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - 0.8 * clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30),
num+"");
this.textsList[num] = text;
}
else {
// Double angle = Math.PI / 2 - i * Math.PI / 30;
Line line = new Line(
centerX + 0.9 * clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - 0.9 * clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30),
centerX + clockRadius * Math.cos(Math.PI / 2 - i * Math.PI / 30),
centerY - clockRadius * Math.sin(Math.PI / 2 - i * Math.PI / 30));
line.setStroke(Color.rgb(254,16,94));
this.linesList[i] = line;
}
}
double sLength = clockRadius * 0.8;
double secondX = centerX + sLength * Math.sin(this.second * (2 * Math.PI / 60));
double secondY= centerY - sLength * Math.cos(this.second * (2 * Math.PI / 60));
Line sLine = new Line(centerX, centerY, secondX, secondY);
sLine.setStroke(Color.RED);
double mLength = clockRadius * 0.65;
double minuteX = centerX + mLength * Math.sin(this.minute * (2 * Math.PI / 60));
double minuteY = centerY - mLength * Math.cos(this.minute * (2 * Math.PI / 60));
Line mLine = new Line(centerX, centerY, minuteX, minuteY);
mLine.setStrokeWidth(3);
mLine.setStroke(Color.BLUE);
double hLength = clockRadius * 0.5;
double hourX = centerX + hLength * Math.sin((this.hour % 12 + this.minute / 60.0) * (2 * Math.PI / 12));
double hourY = centerY - hLength * Math.cos((this.hour % 12 + this.minute / 60.0) * (2 * Math.PI / 12));
Line hLine = new Line(centerX, centerY, hourX, hourY);
hLine.setStrokeWidth(5);
hLine.setStroke(Color.GREEN);
getChildren().clear();
getChildren().add(circle);
getChildren().add(sLine);
getChildren().add(mLine);
getChildren().add(hLine);
for (int i = 0; i < this.linesList.length; i++){
if (i % 5 ==0){
getChildren().add(this.linesList[i]);
getChildren().add(this.textsList[i / 5]);
}
else {
getChildren().add(this.linesList[i]);
}
}
}
@Override
public void setWidth(double width){
super.setWidth(width);
paintClock();
}
@Override
protected void setHeight(double height) {
super.setHeight(height);
paintClock();
}
}
时钟上的刻度坐标和数字坐标计算原理:
package com.example.w9;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DisplayClock extends Application {
public static void main(String[] args) {launch();}
@Override
public void start(Stage primaryStage){
NewClockPane newClockPane = new NewClockPane();
BorderPane borderPane = new BorderPane();
EventHandler<ActionEvent> eventHandler = event -> {
newClockPane.setCurrentTime();
String timeString = newClockPane.getHour() + " : " + newClockPane.getMinute() + " : " + newClockPane.getSecond();
Label timeLabel = new Label(timeString);
timeLabel.setFont(new Font("黑体", 16));
borderPane.setCenter(newClockPane);
borderPane.setBottom(timeLabel);
BorderPane.setAlignment(timeLabel, Pos.TOP_CENTER);
};
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1000), eventHandler)); //永久动画
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
Scene scene = new Scene(borderPane, 600, 600);
primaryStage.setTitle("MyClock");
primaryStage.setScene(scene);
primaryStage.show();
}
}