JavaFX制作一个简单的时钟
程序员文章站
2024-01-31 12:50:13
...
工具:Idea和JavaFX Scene Builder,与Eclipse+JavaFX没什么区别
一、创建JavaFX项目
1. 选择javafx项目
要求:JDK8及其以上
2. javafx项目清单
创建完成后,idea会自动生成一个样例。
再样例上修改或者按照样例重新创建Main类、Controller类及fxml文件也可以
这里我们重新创建这三个文件
3. 创建Main、Controller及fxml
注释:三个的名称都可以自定义
(1)创建Main类
(2)创建Controller类
(3)创建clock.fxml类
(4)clock.fxml中fx:id与Controller类要相同
注释:可以不命名为Controller,但两处要一致
二、JavaFX Scene Builder使用
注释:不会JavaFX Scene Builder的简单使用的看我的另一篇博客,或者百度几下
这里也有点过于仔细
1. 创建两个Circle,一个放大,一个缩小小小小
小小小小圆移动到大圆的圆心处
2. 创建三个Line,作为时分秒的指针,以秒针为例
时分秒指针自行设置,就别百度了
(1)添加Line,设置颜色,粗线
(2)设置精确秒针的位置
先选中小小小小圆,右边->Layout,记录下LayoutY
先选中秒针,右边->Layout,记录下LayoutY
如果秒针的LayoutY与圆心的LayoutY不相同,就[改秒针]的LayoutY
(3)设置秒针的长度
修改秒针的EndX,长度变成一个像样的指针就行
(4)添加时针、分针。原理相同(lue)
3. 添加数字1-12
(1)添加数字12
(2)添加其他数字,直接选择12,然后Ctrl+C,美滋滋。移动(lue)
4. 创建两个Button按钮
(1)添加Button,设置样式,命名等
(2)Ctrl+C,得到另一个按钮,这里我让两个Button重合了
(3)将close按钮设置为不可见(补加的内容)
5. 创建两个Text文本框,
(2)添加Text—–>日期
(2)根据Text日期,复制一个,Text—–>时间
6. 所有的组件添加完毕,下面开始重重点
三、设置重要的组件的fx:id[重]
1.设置三个指针的fx:id
fx:id必须唯一,不能出现相同的fx:id
这里三个fx:id依次设置了,line_hour、line_minute、line_second
2.设置两个Button按钮的fx:id
fx:id依次设为了:btn_start、btn_close**
3.设置两个Text文本框的fx:id
fx:id依次设为了:text_date、text_time**
4.设置AnchorPane的fx:id
4.其他不需要设置fx:id,因为后面没有用到,只是显示
四、完成Main类、Controller类
1.Main类代码如下,基本上是通用的
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("clock.fxml"));
primaryStage.setScene(new Scene(root,556,510));//AnchorPane相同或更大
primaryStage.setTitle("我的时钟");//设置标题
primaryStage.setResizable(false);//设置为不能修改窗口大小
primaryStage.show();
}
}
2.Controller类代码如下
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
public class Controller {
@FXML
private Line line_hour;
@FXML
private Line line_minute;
@FXML
private Line line_second;
@FXML
private Text text_date;
@FXML
private Text text_time;
@FXML
private Button btn_start;
@FXML
private Button btn_close;
}
* 五、Controller类完善(核心、算法) *
1.先给出完成后的Controller类的代码
注释:算法和事件都很简单,看清函数调用就行
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import static java.lang.Math.sin;
import static java.lang.Math.cos;
public class Controller {
@FXML
private Line line_hour;
@FXML
private Line line_minute;
@FXML
private Line line_second;
@FXML
private Text text_date;
@FXML
private Text text_time;
@FXML
private Button btn_start;
@FXML
private Button btn_close;
private boolean clockState = false;//时钟状态
//当前的时间
private Calendar dateTime;
private int hours;
private int minutes;
private int seconds;
//格式化日期、时间
private static SimpleDateFormat dateDF = new SimpleDateFormat("yyyy-MM-dd");
private static SimpleDateFormat timeDF = new SimpleDateFormat("HH:mm:ss");
//根据JavaFX Scene Builder中的组件,计算到的常量
//三个指针的(起点X,起点Y)都相同,根据EndX就是其长度
private static double centerX = 0;//指针的起点X
private static double centerY = 0;//指针的起点Y
private static double hourLength = 60;//时针的长度
private static double minuteLength = 75;//分针的长度
private static double secondLength = 110;//秒针的长度
//引用的全局常量
private static double p2i = 6.28;//p2i =PI * 2
//开启时钟,start按钮的onAction事件
public void startClock() {
clockState = true;
clock();
}
//关闭时钟,close按钮的onAction事件
public void closeClock() {
clockState = false;
clock();
}
//更新获取当前的时间,设置到对象的字段中
private void setTime() {
this.dateTime = Calendar.getInstance();
this.hours = this.dateTime.get(Calendar.HOUR);
this.minutes = this.dateTime.get(Calendar.MINUTE);
this.seconds = this.dateTime.get(Calendar.SECOND);
}
//更新Text文本框的日期时间
private void setTextDateTime() {
text_time.setText("时间: " + timeDF.format(dateTime.getTime()));
text_date.setText("日期: " + dateDF.format(dateTime.getTime()));
}
//显示start、close按钮交叉显示
//即点击start按钮后,start按钮看不见,而close看得见
// 点击close按钮后,close按钮看不见,而start看得见
private void showButton() {
btn_close.setVisible(clockState);
btn_start.setVisible(!clockState);
}
//改变时钟指针的结束坐标(时钟指针移动算法)
private void setClockPointer() {
double hourX = centerX + hourLength * sin((hours + minutes / 60)* p2i / 12);
double hourY= centerY - hourLength * cos((hours + minutes / 60) * p2i / 12);
double minuteX = centerX + minuteLength * sin(minutes * p2i / 60);
double minuteY = centerY - minuteLength * cos(minutes * p2i / 60);
double secondX = centerX + secondLength * sin(seconds * p2i / 60);
double secondY = centerY - secondLength * cos(seconds * p2i / 60);
line_hour.setEndX(hourX);
line_hour.setEndY(hourY);
line_minute.setEndX(minuteX);
line_minute.setEndY(minuteY);
line_second.setEndX(secondX);
line_second.setEndY(secondY);
}
//时钟状态为true就开启新线程,为false时不开启线程(或结束线程)[JDK8 or 9]
private void clock() {
showButton();
if (clockState)
new Thread(() -> {
try {
while (clockState) {
setTime();//刷新当前时间
setTextDateTime();//刷新文本框内容
setClockPointer();//刷新指针的位置
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}