大家好 好久不见 今天给大家带来的实战项目是一个夏日闹钟。学习视频:https://www.bilibili.com/video/BV1pi4y1R7BK 话不多说马上开始
一、项目介绍
1、主体功能
我们要求他能做到什么?:
- 实现显示当前的时间(具体到秒)
- 设置闹钟(可以设置时间)
- 可以修改主题
2、创建步骤
然后的话这是主要的完成步骤:
3、知识点
Java util 包:
还有个GUI 这个也是Java API内的东西
二、项目形成
1、框体
①语法1:形成框体
我们要先创建一个框体 Java的框体叫做 JFrame,然后的话下面的代码就是如何显示框体:
package Clock;
import javax.swing.*;
public class ClockAPP {
public static void main(String[] args) {
// 创建框体 并且设置标题
JFrame frame = new JFrame("Clock");
// 显示框体
frame.setVisible(true);
}
}
当然我们弹出来的框体很随便 是因为我们没有设置字体 框体大小:
那我们肯定要对框体进行一个调整:
package Clock;
import javax.swing.*;
public class ClockAPP {
public static void main(String[] args) {
// 创建框体 并且设置标题
JFrame frame = new JFrame("夏日闹钟");
// 显示框体
frame.setVisible(true);
// 设置框体大小
frame.setSize(500,250);
// 设置框体居中
frame.setLocationRelativeTo(null);
// 设置关闭
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
最终效果:
②语法2:框体中添加字体
代码(带注释):
package Clock;
import javax.swing.*;
import java.awt.*;
public class ClockAPP {
public static void main(String[] args) {
// 创建框体 并且设置标题
JFrame frame = new JFrame("夏日闹钟");
// 显示框体
frame.setVisible(true);
// 设置框体大小
frame.setSize(500,250);
// 设置框体居中
frame.setLocationRelativeTo(null);
// 设置关闭
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建标签对象 开启一个新的框体显示字体的那个玩意
JLabel lbltime = new JLabel();
// 显示字体内容
lbltime.setText("2021-06-22 20:09:20");
// 设置字体大小 字体 加粗
lbltime.setFont(new Font("黑体", Font.BOLD,40));
// 添加到框体中
frame.add(lbltime);
}
}
效果:
如果要居中呢?添加这个就行了:
lbltime.setHorizontalAlignment(JLabel.CENTER);
效果:
2、系统时间
如何显示当前的系统时间?我们可以用代码这么表示:
Date date = new Date();
System.out.println(date);
这样的话就能输出当前的时间 但是你会发现他的时间格式是这样的:
所以我们需要对日期进行格式化 转换成我们需要的样子
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
String time = sdf.format(date);
System.out.println(time);
其实这个很好理解的 第一行就是确定当时的系统时间 第二行就是确定时间的格式 其中 yyyy是年 MM是月 dd是日 HH小时 mm分钟 ss秒 E是日期
然后的话就是将我们创建的系统时间 date 直接代入进去进行转换 最终输入来测试
然后的话我们就要把时间投影到我们 JLable:
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
String time = sdf.format(date);
lbltime.setText(time);
但是的话你会发现这个时间是不会根据系统时间实时刷新的,那我们肯定要搞一个定时刷新的内容了:
// 设置定时器,每隔1000毫秒(1秒)刷新一次时间
Timer timer = new Timer(1000, e -> {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
String time = sdf.format(date);
lbltime.setText(time);
});
// 启动时间
timer.start();
3、右键菜单
虽然说给你们看B站的视频到这边就结束了 后面的内容基本没有为你们讲过,但是我还是稍微负责点 稍微研究了下代码,来继续为你们带来这个实战!
①右键菜单栏创建
首先的话我们要先学会如何创建一个这个右键菜单:
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem("设置闹钟"));
menu.add(new JMenuItem("关于"));
这个看起来都很简单,还有另一种写法:
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem item1 = new JMenuItem("设置闹钟");
JMenuItem item2 = new JMenuItem("关于");
popupMenu.add(item1);
popupMenu.add(item2);
尽量以下面的代码为主,因为这边每级菜单栏都有名称标识,这更能方便我们对菜单功能进行编写!
②鼠标监听
两种写法的内容差不多都是一样的,但是当你启动的时候你会发现:诶 为什么我右键是没有效果的呀?这是因为你没有给你的代码添加一个鼠标操作监听:
// 添加鼠标监听
lbltime.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) menu.show(e.getComponent(), e.getX(), e.getY());
}
public void mouseReleased(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) menu.show(e.getComponent(), e.getX(), e.getY());
}
});
添加后这个监听,你就会发现当你右键完后就可以成功的出发代码内容了!那我们这边设置好的菜单,我们接下来就是要给下一级的菜单来进行赋予功能!
③对下级菜单赋予功能
那么我们现在需要对新的菜单栏来进行添加事件了,首先的话我们上面要求闹钟是可以允许用户输入自定义的时间来设定闹钟的!那么我们的总体思路就是设置一个关于时间的全局变量,通过后面用户设定的时间来对时间的全部变量来进行赋值:
// 全局变量保存闹钟时间
static int alarmHour = -1; // -1表示未设置
static int alarmMinute = -1;
static boolean alarmActive = false; // 标志是否已经提醒过
然后的话我们为这个设置闹钟来赋予功能
// 给菜单项添加事件
item1.addActionListener(evt -> {
// 弹出设置闹钟时间的对话框(使用JSpinner让新手更易理解)
JPanel panel = new JPanel();
panel.add(new JLabel("小时:"));
JSpinner hourSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 23, 1));
panel.add(hourSpinner);
panel.add(new JLabel("分钟:"));
JSpinner minSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 59, 1));
panel.add(minSpinner);
int result = JOptionPane.showConfirmDialog(frame, panel, "设置闹钟时间", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
alarmHour = (Integer) hourSpinner.getValue();
alarmMinute = (Integer) minSpinner.getValue();
alarmActive = false; // 重置提醒标志
JOptionPane.showMessageDialog(frame, String.format("闹钟已设置为 %02d:%02d", alarmHour, alarmMinute));
}
});
还有一个关于还没搞:
item2.addActionListener(evt ->
JOptionPane.showMessageDialog(frame, "夏日闹钟 v1.0\n作者:ZherKing\n简易时钟与闹钟功能", "关于", JOptionPane.INFORMATION_MESSAGE)
);
诶 那这些搞完后,你会发现一个很重要的事情,代码是不是没有判断时间到的提示啊?好像是哦?那么监听的时间该写哪里?是不是我们开头自动刷新的时间的地方?刷新时间的时候顺便判断下闹钟的时间是否到了!所以我们给每一秒判断时间的条件中补上:
// 检查是否到达闹钟时间
if (alarmHour != -1 && alarmMinute != -1) {
Calendar cal = Calendar.getInstance();
int nowHour = cal.get(Calendar.HOUR_OF_DAY);
int nowMin = cal.get(Calendar.MINUTE);
// 只在“刚好到点”提醒一次
if (nowHour == alarmHour && nowMin == alarmMinute && !alarmActive) {
alarmActive = true; // 设置已提醒
// 播放系统提示音
Toolkit.getDefaultToolkit().beep();
// 弹窗提醒
JOptionPane.showMessageDialog(frame, String.format("闹钟时间到!现在是 %02d:%02d", alarmHour, alarmMinute), "闹钟提醒", JOptionPane.WARNING_MESSAGE);
}
// 如果时间已过,允许下次设置后再次提醒
if (nowHour != alarmHour || nowMin != alarmMinute) {
alarmActive = false;
}
}
这样的话我们的代码内容大体框架也差不多完成了!
4、主题设置
啊 还有个主题还没搞勒…补充下吧!还是在我们的菜单栏多添加一个主题
JMenuItem item3 = new JMenuItem("设置主题");
和上面设置闹钟一样,我们也需要一个初始的主题颜色来作为全部变量:
// 新增:主题相关变量
static Color bgColor = Color.WHITE; // 背景色
static Color fgColor = Color.BLACK; // 字体色
然后设置一个主题的事件:
// 设置主题
item3.addActionListener(evt -> {
String[] options = {"浅色主题", "深色主题", "蓝色主题", "绿色主题"};
int choice = JOptionPane.showOptionDialog(frame, "请选择主题:", "设置主题",
JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
// 根据选择设置不同的颜色
switch (choice) {
case 0: // 浅色
bgColor = Color.WHITE;
fgColor = Color.BLACK;
break;
case 1: // 深色
bgColor = Color.DARK_GRAY;
fgColor = Color.WHITE;
break;
case 2: // 蓝色
bgColor = new Color(30, 144, 255);
fgColor = Color.WHITE;
break;
case 3: // 绿色
bgColor = new Color(0, 150, 136);
fgColor = Color.WHITE;
break;
default:
return; // 没选直接退出
}
// 设置背景色和字体色
frame.getContentPane().setBackground(bgColor);
lbltime.setForeground(fgColor);
然后主题初始化:
// 初始化主题
frame.getContentPane().setBackground(bgColor);
lbltime.setForeground(fgColor);
那到这里为止我们的代码内容也差不多完成了!
三、代码源码
package Clock;
import javax.swing.*;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class ClockAPP {
// 全局变量保存闹钟时间
static int alarmHour = -1; // -1表示未设置
static int alarmMinute = -1;
static boolean alarmActive = false; // 标志是否已经提醒过
// 新增:主题相关变量
static Color bgColor = Color.WHITE; // 背景色
static Color fgColor = Color.BLACK; // 字体色
public static void main(String[] args) {
// 创建框体 并且设置标题
JFrame frame = new JFrame("夏日闹钟");
// 显示框体
frame.setVisible(true);
// 设置框体大小
frame.setSize(500,250);
// 设置框体居中
frame.setLocationRelativeTo(null);
// 设置关闭
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 开启一个新的框体显示字体的那个玩意
JLabel lbltime = new JLabel();
// 设置字体大小 字体 加粗
lbltime.setFont(new Font("黑体", Font.BOLD,40));
// 居中字体
lbltime.setHorizontalAlignment(JLabel.CENTER);
// 添加到框体中
frame.add(lbltime);
// 创建菜单栏
JPopupMenu popupMenu = new JPopupMenu();
// 设置菜单栏的内容
JMenuItem item1 = new JMenuItem("设置闹钟");
JMenuItem item3 = new JMenuItem("设置主题");
JMenuItem item2 = new JMenuItem("关于");
// 添加
popupMenu.add(item1);
popupMenu.add(item2);
popupMenu.add(item3);
// 给菜单项添加事件
item1.addActionListener(evt -> {
// 弹出设置闹钟时间的对话框(使用JSpinner让新手更易理解)
JPanel panel = new JPanel();
panel.add(new JLabel("小时:"));
JSpinner hourSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 23, 1));
panel.add(hourSpinner);
panel.add(new JLabel("分钟:"));
JSpinner minSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 59, 1));
panel.add(minSpinner);
int result = JOptionPane.showConfirmDialog(frame, panel, "设置闹钟时间", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
alarmHour = (Integer) hourSpinner.getValue();
alarmMinute = (Integer) minSpinner.getValue();
alarmActive = false; // 重置提醒标志
JOptionPane.showMessageDialog(frame, String.format("闹钟已设置为 %02d:%02d", alarmHour, alarmMinute));
}
});
item2.addActionListener(evt ->
JOptionPane.showMessageDialog(frame, "夏日闹钟 v1.0\n作者:ZherKing\n简易时钟与闹钟功能", "关于", JOptionPane.INFORMATION_MESSAGE)
);
// 添加鼠标监听
lbltime.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
@Override
public void mouseReleased(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
// 设置主题
item3.addActionListener(evt -> {
String[] options = {"浅色主题", "深色主题", "蓝色主题", "绿色主题"};
int choice = JOptionPane.showOptionDialog(frame, "请选择主题:", "设置主题",
JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
// 根据选择设置不同的颜色
switch (choice) {
case 0: // 浅色
bgColor = Color.WHITE;
fgColor = Color.BLACK;
break;
case 1: // 深色
bgColor = Color.DARK_GRAY;
fgColor = Color.WHITE;
break;
case 2: // 蓝色
bgColor = new Color(30, 144, 255);
fgColor = Color.WHITE;
break;
case 3: // 绿色
bgColor = new Color(0, 150, 136);
fgColor = Color.WHITE;
break;
default:
return; // 没选直接退出
}
// 设置背景色和字体色
frame.getContentPane().setBackground(bgColor);
lbltime.setForeground(fgColor);
});
// 设置定时器,每隔1000毫秒(1秒)刷新一次时间
Timer timer = new Timer(1000, e -> {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
String time = sdf.format(date);
lbltime.setText(time);
// 检查是否到达闹钟时间
if (alarmHour != -1 && alarmMinute != -1) {
Calendar cal = Calendar.getInstance();
int nowHour = cal.get(Calendar.HOUR_OF_DAY);
int nowMin = cal.get(Calendar.MINUTE);
// 只在“刚好到点”提醒一次
if (nowHour == alarmHour && nowMin == alarmMinute && !alarmActive) {
alarmActive = true; // 设置已提醒
// 播放系统提示音
Toolkit.getDefaultToolkit().beep();
// 弹窗提醒
JOptionPane.showMessageDialog(frame, String.format("闹钟时间到!现在是 %02d:%02d", alarmHour, alarmMinute), "闹钟提醒", JOptionPane.WARNING_MESSAGE);
}
// 如果时间已过,允许下次设置后再次提醒
if (nowHour != alarmHour || nowMin != alarmMinute) {
alarmActive = false;
}
}
});
// 启动时间
timer.start();
// 初始化主题
frame.getContentPane().setBackground(bgColor);
lbltime.setForeground(fgColor);
}
}