一、最终效果预览
运行程序后,窗口右下角显示实时更新的时间,每秒刷新一次:
时间格式为
yyyy.MM.dd hh:mm:ss,每秒自动更新,精确到秒。
二、核心知识点
2.1 Timeline:JavaFX 的时间轴动画
Timeline是 JavaFX 动画系统的核心类,用于按时间线执行一系列动作:
| 属性/方法 | 说明 |
|---|---|
new KeyFrame(Duration, EventHandler) | 定义关键帧:到达指定时间后执行事件 |
setCycleCount(int) | 设置循环次数,INDEFINITE表示无限循环 |
play() | 启动动画 |
pause() | 暂停动画 |
stop() | 停止动画 |
2.2 SimpleDateFormat 时间格式化
DateFormatcurrentTime=newSimpleDateFormat("yyyy.MM.dd hh:mm:ss");常用格式符号:
| 符号 | 含义 | 示例 |
|---|---|---|
yyyy | 四位年份 | 2026 |
MM | 两位月份 | 06 |
dd | 两位日期 | 13 |
HH | 24小时制 | 21 |
hh | 12小时制 | 09 |
mm | 分钟 | 49 |
ss | 秒 | 30 |
注意:
HH是24小时制,hh是12小时制。建议使用HH避免上午下午混淆。
三、完整代码实现
importjavafx.application.Application;importjavafx.event.ActionEvent;importjavafx.event.EventHandler;importjavafx.geometry.Insets;importjavafx.geometry.Pos;importjavafx.scene.Scene;importjavafx.scene.control.Label;importjavafx.scene.layout.BorderPane;importjavafx.scene.text.Font;importjavafx.stage.Stage;importjavafx.animation.KeyFrame;importjavafx.animation.Timeline;importjavafx.util.Duration;importjava.text.DateFormat;importjava.text.SimpleDateFormat;importjava.util.Date;publicclassRealTimeClockextendsApplication{@Overridepublicvoidstart(StageprimaryStage){// 1. 创建时间标签LabeltimeLabel=newLabel();timeLabel.setFont(newFont(20));// 设置字体大小为20// 2. 设置时间格式DateFormatdateFormat=newSimpleDateFormat("yyyy.MM.dd HH:mm:ss");// 3. 创建事件处理器:每秒更新时间EventHandler<ActionEvent>eventHandler=e->{StringcurrentTime=dateFormat.format(newDate());timeLabel.setText(currentTime);System.out.println(currentTime);// 控制台同步输出};// 4. 创建 Timeline 动画Timelineanimation=newTimeline(newKeyFrame(Duration.millis(1000),eventHandler));animation.setCycleCount(Timeline.INDEFINITE);// 无限循环animation.play();// 启动动画// 5. 布局设置:将时间标签放在右下角BorderPaneroot=newBorderPane();root.setPadding(newInsets(20));BorderPane.setAlignment(timeLabel,Pos.BOTTOM_RIGHT);root.setBottom(timeLabel);// 6. 创建场景Scenescene=newScene(root,400,300);primaryStage.setTitle("JavaFX 实时时钟");primaryStage.setScene(scene);primaryStage.show();}publicstaticvoidmain(String[]args){launch(args);}}四、运行效果展示
4.1 界面效果
窗口右下角显示当前时间,每秒自动刷新。同时控制台也会每秒打印一次时间日志。
4.2 控制台输出
2026.06.13 21:49:00 2026.06.13 21:49:01 2026.06.13 21:49:02 2026.06.13 21:49:03 ...五、关键代码解析
5.1 Timeline 的工作原理
Timelineanimation=newTimeline(newKeyFrame(Duration.millis(1000),eventHandler));Duration.millis(1000):每隔 1000 毫秒(1秒)触发一次eventHandler:每次触发时执行的事件setCycleCount(Timeline.INDEFINITE):无限重复,不会自动停止
Timeline 执行流程:
启动 (play) ├── 等待 1000ms ├── 执行 eventHandler(更新时间) ├── 等待 1000ms ├── 执行 eventHandler(更新时间) └── ...无限循环5.2 为什么用 Timeline 而不是 Thread?
| 方式 | 优点 | 缺点 |
|---|---|---|
Timeline | JavaFX 原生支持,自动在 UI 线程更新,线程安全 | 精度受限于 JavaFX 帧率 |
Thread + sleep | 简单直观 | 需要手动调用Platform.runLater()更新 UI,容易出错 |
AnimationTimer | 适合高帧率动画(如游戏) | 每秒60次回调,不适合低频更新 |
对于每秒更新一次的需求,
Timeline是最简洁、最安全的选择。
六、进阶:多功能时钟面板
将实时时间与其他功能结合,打造一个更实用的状态栏:
importjavafx.application.Application;importjavafx.geometry.Insets;importjavafx.geometry.Pos;importjavafx.scene.Scene;importjavafx.scene.control.Label;importjavafx.scene.layout.HBox;importjavafx.scene.text.Font;importjavafx.scene.text.FontWeight;importjavafx.stage.Stage;importjavafx.animation.KeyFrame;importjavafx.animation.Timeline;importjavafx.util.Duration;importjava.text.SimpleDateFormat;importjava.util.Date;publicclassStatusBarClockextendsApplication{privateLabeltimeLabel;privateLabelstatusLabel;privateintseconds=0;@Overridepublicvoidstart(StageprimaryStage){// 状态标签statusLabel=newLabel("系统运行中");statusLabel.setFont(Font.font(14));// 时间标签timeLabel=newLabel();timeLabel.setFont(Font.font("Consolas",FontWeight.BOLD,16));// 布局HBoxstatusBar=newHBox(20);statusBar.setAlignment(Pos.CENTER_RIGHT);statusBar.setPadding(newInsets(10,20,10,20));statusBar.getChildren().addAll(statusLabel,timeLabel);// Timeline:每秒更新Timelinetimeline=newTimeline(newKeyFrame(Duration.seconds(1),e->update()));timeline.setCycleCount(Timeline.INDEFINITE);timeline.play();Scenescene=newScene(statusBar,500,50);primaryStage.setTitle("状态栏时钟");primaryStage.setScene(scene);primaryStage.show();}privatevoidupdate(){// 更新时间SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");timeLabel.setText(sdf.format(newDate()));// 更新运行时长seconds++;if(seconds%5==0){statusLabel.setText("已运行 "+seconds+" 秒");}}publicstaticvoidmain(String[]args){launch(args);}}七、总结
| 知识点 | 要点 |
|---|---|
| Timeline | 使用KeyFrame定义定时任务,INDEFINITE无限循环 |
| SimpleDateFormat | "yyyy.MM.dd HH:mm:ss"格式化当前时间 |
| 线程安全 | Timeline 自动在 JavaFX UI 线程执行,无需手动切换 |
| 字体设置 | new Font(20)或Font.font("Consolas", FontWeight.BOLD, 16) |