话不多说,咱们先看效果。
![](https://img-blog.csdnimg.cn/20200302182341482.gif)
分级结构:
![](https://img-blog.csdnimg.cn/20200302182408178.png)
Cale_Main部分
/*
*所使用的环境是IDE,java 11 版本,以下会存在原子类型。
*java.concurrent.atomic 包含了许多有用的类实现原子操作。
* 原子操作是多个线程同时执行,确保其是安全的,且并不需要synchronized 关键字。
* 这里使用了 AtomicInteger、AtomicReference,这里主要演示AtomicInteger类。
* 这些指令通常比同步块要快。
* 所以在只需要并发修改单个可变变量的情况下,
* 优先使用原子类,而不是使用锁机制实现。
* 这里使用原子类型的原因是因为IDE的自动提示功能。
*
*/
package work2;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Cale_Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
public void start(Stage primaryStage) {
primaryStage.setResizable(false);
Cale_Pane cale = new Cale_Pane();
Scene scene = new Scene(cale, 860, 340);
primaryStage.setTitle("我的日历");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Cale_Pane部分
package work2;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.util.Duration;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static javafx.geometry.HPos.CENTER;
import static javafx.geometry.HPos.RIGHT;
class Cale_Pane extends Pane {
private int year;
private int final_year;
private int month;
private int final_month;
private int day;
private int final_day;
private int firstDayOfWeek;
private int totalDayOfMonth;
private String NowTime;
private AtomicReference<Text> text1 = new AtomicReference<>(new Text());
//set week label
private Label[] week_label = new Label[7];
// set cale[8][7]
private Label[][] cale_label = new Label[6][7];
//set_row and col
private AtomicInteger next_month_rowIndex = new AtomicInteger();
private AtomicInteger next_month_columnIndex = new AtomicInteger();
private AtomicInteger tmp_day = new AtomicInteger(1);
Cale_Pane() {
Calendar calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
day = calendar.get(Calendar.DAY_OF_MONTH);
totalDayOfMonth = calendar.getActualMaximum(Calendar.DATE);
calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
paint();
}
private void paint() {
Now_Time cp = new Now_Time();
final_year = year;
final_month = month;
final_day = day;
BorderPane bp = new BorderPane();
GridPane gridPane = new GridPane();
bp.setTop(gridPane);
String[] week = new String[]{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
gridPane.setPadding(new Insets(30, 30, 10, 10));
text1.get().setText(year + "年" + month + "月");
text1.get().setStroke(Color.GREEN);
text1.get().setFont(Font.font(20));
gridPane.setAlignment(Pos.CENTER);
gridPane.add(text1.get(), 0, 0);
GridPane.setColumnSpan(text1.get(), 7);
GridPane.setHalignment(text1.get(), CENTER);
//set week
for (int i = 0; i < 7; i++) {
week_label[i] = new Label(week[i]);
week_label[i].setFont(Font.font("微软雅黑", FontWeight.BOLD, 20));
if (i == 0 || i == 6) week_label[i].setTextFill(Color.RED);
GridPane.setColumnSpan(week_label[i], 2);
gridPane.add(week_label[i], i, 1);
gridPane.getColumnConstraints().add(new ColumnConstraints(30));
GridPane.setHalignment(week_label[i], HPos.LEFT);
}
// System.out.println(return_last_month_days());
//judge and set last month
if (firstDayOfWeek != 7) {
for (int j = 0; j < firstDayOfWeek; j++) {
cale_label[0][j] = new Label(j + return_last_month_days() - firstDayOfWeek + 1 + "");
cale_label[0][j].setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 20));
cale_label[0][j].setTextFill(Color.GRAY);
gridPane.add(cale_label[0][j], j, 2);
GridPane.setHalignment(cale_label[0][j], RIGHT);
}
}
//set now month
for (int j = 0; j < totalDayOfMonth; j++) {
int k = firstDayOfWeek + j;
cale_label[k / 7][k % 7] = new Label(j + 1 + "");
cale_label[k / 7][k % 7].setFont(Font.font("Times New Roman", FontWeight.BOLD, 20));
// System.out.println(firstDayOfWeek);
if ((k % 7 == 0) || (k % 7 == 6)) cale_label[k / 7][k % 7].setTextFill(Color.RED);
if (j + 1 == final_day && final_month == month && final_year == year) {
cale_label[k / 7][k % 7].setFont(Font.font("Cooper Black", FontWeight.BOLD, 20));
cale_label[k / 7][k % 7].setTextFill(Color.CORAL);
}
gridPane.add(cale_label[k / 7][k % 7], k % 7, 2 + k / 7);
next_month_rowIndex.set(2 + k / 7);
next_month_columnIndex.set(k % 7);
GridPane.setHalignment(cale_label[k / 7][k % 7], RIGHT);
}
//set next month
//!!! having a bug,it's the next_month_columnIndex and rowIndex
next_month_columnIndex.set(((next_month_columnIndex.get() + 1) % 7));
next_month_rowIndex.addAndGet((next_month_columnIndex.get() == 0 ? 1 : 0));
while (!(next_month_columnIndex.get() == 0 && next_month_rowIndex.get() == 8)) {
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()] = new Label(tmp_day + "");
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()].setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 20));
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()].setTextFill(Color.GRAY);
gridPane.add(cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()], next_month_columnIndex.get() % 7, next_month_rowIndex.get());
GridPane.setHalignment(cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()], RIGHT);
tmp_day.getAndIncrement();
next_month_columnIndex.set((next_month_columnIndex.incrementAndGet()) % 7);
//the key
next_month_rowIndex.addAndGet((next_month_columnIndex.get() == 0 ? 1 : 0));
}
//GET NEW
GridPane gridPane2 = new GridPane();
Button setting = new Button("Setting");
Button Prior = new Button("Prior");
Button Next = new Button("Next");
Button Now = new Button("Now");
GridPane.setColumnSpan(setting, 4);
GridPane.setColumnSpan(Prior, 4);
// GridPane.setHalignment(Prior, CENTER_LEFT);
GridPane.setColumnSpan(Next, 4);
// GridPane.setHalignment(Next, CENTER);
GridPane.setColumnSpan(Now, 4);
// GridPane.setHalignment(Now, CENTER);
gridPane2.add(setting, 2, 1);
gridPane2.add(Prior, 8, 1);
gridPane2.add(Next, 16, 1);
gridPane2.add(Now, 24, 1);
//gridPane2.setAlignment(Pos.CENTER);
//set pane2 gap
gridPane2.setHgap(28);
gridPane2.setVgap(0);
//set pane gap
gridPane.setHgap(94);
gridPane.setVgap(5);
bp.setBottom(gridPane2);
//点击prior
Prior.setOnAction(e -> {
//to clear
//gridPane.getChildren().clear();
//init
to_add_month(-2);
to_update_information();
});
//点击Next
Next.setOnAction(e -> {
to_add_month(0);
to_update_information();
});
//点击Now
Now.setOnAction(e -> {
Calendar set_calendar = Calendar.getInstance();
set_calendar.set(final_year, final_month - 1, final_day);
year = set_calendar.get(Calendar.YEAR);
month = set_calendar.get(Calendar.MONTH) + 1;
day = set_calendar.get(Calendar.DAY_OF_MONTH);
totalDayOfMonth = set_calendar.getActualMaximum(Calendar.DATE);
set_calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfWeek = set_calendar.get(Calendar.DAY_OF_WEEK) - 1;
to_update_information();
});
setting.setOnAction(e -> {
Setting_date set = new Setting_date(year, month);
set.show();
//System.out.println(set.getTo_return_month());
int tmp_year = set.getTo_return_year();
int tmp_month = set.getTo_return_month();
Calendar set_calendar = Calendar.getInstance();
set_calendar.set(tmp_year, tmp_month - 1, final_day);
year = set_calendar.get(Calendar.YEAR);
month = set_calendar.get(Calendar.MONTH) + 1;
day = set_calendar.get(Calendar.DAY_OF_MONTH);
totalDayOfMonth = set_calendar.getActualMaximum(Calendar.DATE);
set_calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfWeek = set_calendar.get(Calendar.DAY_OF_WEEK) - 1;
to_update_information();
});
StackPane nt = new StackPane();
EventHandler<ActionEvent> eventHandler = e -> {
nt.getChildren().clear();
NowTime = cp.setCurrentTime();
Text tt = new Text(NowTime);
tt.setFont(Font.font("Times New Roman", 20));
nt.getChildren().add(tt);
};
Timeline animation = new Timeline(
new KeyFrame(Duration.millis(1000), eventHandler));
animation.setCycleCount(Timeline.INDEFINITE);
animation.play();
gridPane2.add(nt, 14, 0);
// gridPane.add(sp, 14, 4);
nt.setAlignment(Pos.BOTTOM_CENTER);
//bp.setRight(sp);
// sp.setAlignment(Pos.BOTTOM_RIGHT);
getChildren().add(bp);
Start_Tishi.display("起始窗口", "Today is " +
year + " year " + month + " month " + day + " day "
+ week[day % 7]);
}
private void to_add_month(int add) {
Calendar set_calendar = Calendar.getInstance();
set_calendar.set(year, month + add, day);
year = set_calendar.get(Calendar.YEAR);
month = set_calendar.get(Calendar.MONTH) + 1;
day = set_calendar.get(Calendar.DAY_OF_MONTH);
totalDayOfMonth = set_calendar.getActualMaximum(Calendar.DATE);
set_calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfWeek = set_calendar.get(Calendar.DAY_OF_WEEK) - 1;
}
private int return_last_month_days() {
Calendar last_month;
last_month = Calendar.getInstance();
last_month.set(year, month - 1 - 1, day);
return last_month.getActualMaximum(Calendar.DATE);
}
private void to_update_information() {
next_month_rowIndex.set(0);
next_month_columnIndex.set(0);
text1.get().setText(year + "年" + month + "月");
// set last month
if (firstDayOfWeek != 7) {
for (int j = 0; j < firstDayOfWeek; j++) {
cale_label[0][j].setText(j + return_last_month_days() - firstDayOfWeek + 1 + "");
cale_label[0][j].setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 20));
cale_label[0][j].setTextFill(Color.GRAY);
}
}
//set now month
for (int j = 0; j < totalDayOfMonth; j++) {
int k = firstDayOfWeek + j;
cale_label[k / 7][k % 7].setText(j + 1 + "");
if (j + 1 == final_day && final_month == month && final_year == year) {
if ((k % 7 == 0) || (k % 7 == 6)) cale_label[k / 7][k % 7].setTextFill(Color.RED);
cale_label[k / 7][k % 7].setFont(Font.font("Cooper Black", FontWeight.BOLD, 20));
cale_label[k / 7][k % 7].setTextFill(Color.CORAL);
} else {
cale_label[k / 7][k % 7].setFont(Font.font("Times New Roman", FontWeight.BOLD, 20));
cale_label[k / 7][k % 7].setTextFill(Color.BLACK);
if ((k % 7 == 0) || (k % 7 == 6)) cale_label[k / 7][k % 7].setTextFill(Color.RED);
}
next_month_rowIndex.set(2 + k / 7);
next_month_columnIndex.set(k % 7);
}
//set next month
tmp_day.set(1);
//!!! having a bug,it's the next_month_columnIndex and rowIndex
next_month_columnIndex.set(((next_month_columnIndex.get() + 1) % 7));
next_month_rowIndex.addAndGet((next_month_columnIndex.get() == 0 ? 1 : 0));
while (!(next_month_columnIndex.get() == 0 && next_month_rowIndex.get() == 8)) {
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()].setText(tmp_day + "");
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()].setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 20));
cale_label[next_month_rowIndex.get() - 2][next_month_columnIndex.get()].setTextFill(Color.GRAY);
tmp_day.getAndIncrement();
next_month_columnIndex.set((next_month_columnIndex.incrementAndGet()) % 7);
//the key
next_month_rowIndex.addAndGet((next_month_columnIndex.get() == 0 ? 1 : 0));
}
}
}
Now_Time部分
package work2;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
public class Now_Time extends Pane {
private int hour;
private int minute;
private int second;
Now_Time() {
setCurrentTime();
}
String setCurrentTime() {
String str1, str2, str3;
Calendar calendar = new GregorianCalendar();
this.hour = calendar.get(Calendar.HOUR_OF_DAY);
this.minute = calendar.get(Calendar.MINUTE);
this.second = calendar.get(Calendar.SECOND);
str1 = String.valueOf(hour);
str2 = String.valueOf(minute);
str3 = String.valueOf(second);
if (hour < 10) {
str1 = "0" + hour;
}
if (minute < 10) {
str2 = "0" + minute;
}
if (second < 10) {
str3 = "0" + second;
}
paint();
return str1 + " : " + str2 + " : " + str3;
}
protected void paint() {
getChildren().clear();
double w = 200;
double h = 200;
double clockRadius = Math.min(w, h) * 0.8 * 0.5;
double centerX = w / 2;
double centerY = h / 2;
double sLength = clockRadius * 0.8;
double secondX = centerX + sLength * Math.sin(second * (2 * Math.PI) / 60);
double secondY = centerY - sLength * Math.cos(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(minute * (2 * Math.PI) / 60);
double minuteY = centerY - mLength * Math.cos(minute * (2 * Math.PI) / 60);
Line mLine = new Line(centerX, centerY, minuteX, minuteY);
mLine.setStroke(Color.BLUE);
double hLength = clockRadius * 0.5;
double hourX = centerX + hLength * Math.sin(hour * (2 * Math.PI) / 12);
double hourY = centerY - hLength * Math.cos(hour * (2 * Math.PI) / 12);
Line hLine = new Line(centerX, centerY, hourX, hourY);
mLine.setStroke(Color.GREEN);
getChildren().addAll(sLine, mLine, hLine);
}
}
Setting_date部分
package work2;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Modality;
import javafx.stage.Stage;
class Setting_date {
private int to_return_year;
private int to_return_month;
private int year;
private int month;
Setting_date() {
}
Setting_date(int year, int month) {
this.to_return_year = this.year = year;
this.to_return_month = this.month = month;
}
void show(){
Stage stage = new Stage();
stage.setResizable(false);
stage.setTitle("Setting");
//modality要使用Modality.APPLICATION_MODEL
stage.initModality(Modality.APPLICATION_MODAL);
stage.setMinWidth(300);
stage.setMinHeight(250);
BorderPane bp = new BorderPane();
Label label_year = new Label("Year");
Label label_month = new Label("month");
label_year.setTextFill(Color.rgb(100, 107, 48));
label_year.setFont(Font.font("Times New Roman", 26));
label_month.setTextFill(Color.rgb(100, 107, 48));
label_month.setFont(Font.font("Times New Roman", 26));
GridPane gp = new GridPane();
gp.add(label_year, 0, 0);
gp.add(label_month, 2, 0);
gp.setHgap(40);
gp.setAlignment(Pos.CENTER);
ObservableList<Integer> year_12 = FXCollections.observableArrayList();
for (int i = year + 3; i >= year; i--)
year_12.add(i);
for (int i = year - 1; i >= year - 100; i--)
year_12.add(i);
ListView<Integer> left_year = new ListView<>(year_12);
left_year.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
left_year.setPrefSize(150, 200);
left_year.getSelectionModel().selectedItemProperty().addListener(ov->{
//System.out.println(left_year.getSelectionModel().getSelectedIndices());
//System.out.println(left_year.getSelectionModel().getSelectedItem());
this.to_return_year = left_year.getSelectionModel().getSelectedItem();
});
ObservableList<Integer> month_12 = FXCollections.observableArrayList(1,2,3,4,5,6,7,8,9,10,11,12);
ListView<Integer> right_month = new ListView<>(month_12);
right_month.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
right_month.setPrefSize(150, 200);
right_month.getSelectionModel().selectedItemProperty().addListener(ov -> {
this.to_return_month = right_month.getSelectionModel().getSelectedItem();
});
Button button = new Button("关闭设置");
button.setOnAction(e -> stage.close());
button.setTextFill(Color.rgb(222,156,83));
button.setFont(Font.font("微软雅黑", 16));
GridPane gp2 = new GridPane();
gp2.add(button,0,0);
gp2.setAlignment(Pos.CENTER);
bp.setTop(gp);
bp.setLeft(left_year);
bp.setRight(right_month);
bp.setBottom(gp2);
Scene scene = new Scene(bp);
stage.setScene(scene);
//使用showAndWait()先处理这个窗口,而如果不处理,main中的那个窗口不能响应
stage.showAndWait();
}
int getTo_return_year() {
return to_return_year;
}
int getTo_return_month() {
return to_return_month;
}
}
Start_Tishi部分
package work2;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Duration;
class Start_Tishi {
private static String NowTime;
static void display(String title, String message){
Stage window = new Stage();
window.setResizable(false);
window.setTitle(title);
//modality要使用Modality.APPLICATION_MODEL
window.initModality(Modality.APPLICATION_MODAL);
window.setMinWidth(600);
window.setMinHeight(250);
Button button = new Button("欢迎您的使用");
button.setOnAction(e -> window.close());
button.setTextFill(Color.rgb(222,156,83));
button.setFont(Font.font("微软雅黑", 18));
Label label = new Label(message);
label.setTextFill(Color.rgb(100, 107, 48));
label.setFont(Font.font("Times New Roman", 26));
VBox layout = new VBox(10);
StackPane nt = new StackPane();
Now_Time cp = new Now_Time();
EventHandler<ActionEvent> eventHandler = e -> {
nt.getChildren().clear();
NowTime = (String) cp.setCurrentTime();
Text tt = new Text(NowTime);
tt.setFont(Font.font("Times New Roman", 20));
nt.getChildren().add(tt);
};
Timeline animation = new Timeline(
new KeyFrame(Duration.millis(1000), eventHandler));
animation.setCycleCount(Timeline.INDEFINITE);
animation.play();
layout.getChildren().addAll(label , nt, button);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout);
window.setScene(scene);
//使用showAndWait()先处理这个窗口,而如果不处理,main中的那个窗口不能响应
window.showAndWait();
}
}