import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
private static final int LOOP_COUNT = 5; // 重复播放的次数
private JLabel labelClock, labelAlarm, labelNextAlarm
;
private SetDialog setDialog;
private JPanel topPanel, alarmPanel
;
private boolean timeReached = true;
public AlarmClock() {
super("闹钟");
}
public void launch() {
setSize(400, 300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane
().
setLayout(new BorderLayout()); // 利用边界布局将界面分割成上中下三部分
labelAlarm
= new JLabel("闹钟定时已到!");
labelNextAlarm
= new JLabel(); // 指示下一次闹钟时间
alarmPanel.add(labelAlarm);
alarmPanel.add(btnClose);
topPanel.add(alarmPanel);
topPanel.add(labelNextAlarm);
alarmPanel.setVisible(false); // 初始隐藏顶部提示栏
labelClock.setFont(font);
labelClock.
setHorizontalAlignment(JLabel.
CENTER); // 文本居中
getContentPane
().
add(labelClock,
BorderLayout.
CENTER); // 界面中部
btnSet.addActionListener(this); // 设置按钮的点击事件
btnClose.addActionListener(this); // 顶部确定按钮的点击事件
setLocationRelativeTo(null); // 界面居中
setDialog = new SetDialog(this); // 初始化设置对话框
try { // 初始化闹钟声音
// 目前发现wav格式的文件是可以支持的,mp3不支持
AlarmClock.class.getResource("music.wav"));
clip.open(ais);
ais.close();
int loop = LOOP_COUNT <= 0 ? 1 : LOOP_COUNT;
final long totalFrames = ais.getFrameLength() * loop;
// 当闹钟音乐播放结束时,自动隐藏顶部提示栏
if(e.getFramePosition() >= totalFrames) {
stopAlarm();
}
}
});
e.printStackTrace();
e.printStackTrace();
e.printStackTrace();
}
initTimer();
}
public static void main
(String[] args
) {
new AlarmClock().launch(); // 启动主界面
}
Object source
= e.
getSource();
if(source == btnSet) { // 点击设置按钮时弹出设置界面,以模对话框显示
setDialog.setVisible(true);
} else if(source == btnClose) { // 点击顶部确定按钮时隐藏顶部提示栏
stopAlarm();
}
}
private void initTimer() {
timer
= new Timer(); // 初始化倒计时任务
// 开始倒计时
@Override
public void run() {
int hour
= cal.
get(Calendar.
HOUR_OF_DAY);
// 设置倒计时文本
labelClock.
setText(String.
format("%02d : %02d : %02d", hour, min, sec
));
if(null != alarmCal && !timeReached) {
int alarmHour
= alarmCal.
get(Calendar.
HOUR_OF_DAY);
int alarmMin
= alarmCal.
get(Calendar.
MINUTE);
if(alarmHour == hour && alarmMin == min) { // 到时间时播放声音
timeReached = true;
System.
out.
println("Time over");
startAlarm();
}
}
}
}, 0, 1000L); // 每隔1秒刷新倒计时文本
}
/**
* 开始计时
* @param hour
* @param minute
*/
public void startTimer(int hour, int minute) {
alarmCal.
set(Calendar.
HOUR_OF_DAY, hour
);
labelNextAlarm.setText("下次闹钟时间:" + df.format(alarmCal.getTime()));
timeReached = false;
}
/**
* 取消倒计时任务
*/
public void cancelTimer() {
labelNextAlarm.setText("");
alarmCal = null;
}
private void startAlarm() { // 开始播放提示音
if(null != clip) {
alarmPanel.setVisible(true); // 显示顶部提示栏
clip.setFramePosition(0); // 将音频帧重置为第0帧
clip.loop(LOOP_COUNT); // 开始循环播放
}
labelNextAlarm.setText("");
}
private void stopAlarm() { // 停止播放提示音
if(null != clip && clip.isRunning()) {
clip.stop(); // 结束播放
}
labelNextAlarm.setText("");
alarmPanel.setVisible(false); // 隐藏顶部提示栏
}
/**
* 闹钟设置页面
*/
private JLabel labelHour, labelMin
;
private JPanel mainPanel, labelPanel, buttonPanel
;
private JButton btnOk, btnCancel, btnBack
;
public SetDialog
(Frame frame
) {
super(frame);
setTitle("设置");
setModal(true); // 设置为模窗口,就是说在本弹窗未消失时不允许点击主界面。
setSize(300, 150);
// 显示时分
labelHour.
setHorizontalAlignment(JLabel.
CENTER);
labelMin.
setHorizontalAlignment(JLabel.
CENTER);
// 上面的部分用网格布局将各组件以2x2的格子放进去
labelPanel.add(labelHour);
labelPanel.add(labelMin);
labelPanel.add(textHour);
labelPanel.add(textMin);
// 时分输入框添加按键监听,只允许输入数字
textHour.addKeyListener(this);
textMin.addKeyListener(this);
// 初始化按钮
// 下面的按钮依次居中放进去
buttonPanel.add(btnBack);
buttonPanel.add(btnCancel);
buttonPanel.add(btnOk);
// 初始化主面板,将主面板分割为上下两部分
mainPanel.
add(labelPanel,
BorderLayout.
CENTER); // 上面显示时分的组件
setContentPane(mainPanel);
// 设置按钮监听
btnBack.addActionListener(this);
btnOk.addActionListener(this);
btnCancel.addActionListener(this);
cal.
add(Calendar.
HOUR,
1); // 默认设置为当前时间加1小时的整点时间
int hour
= cal.
get(Calendar.
HOUR_OF_DAY);
textHour.
setText(String.
format("%02d", hour
));
textMin.
setText(String.
format("%02d", min
));
setLocationRelativeTo(frame);
}
}
public void keyReleased
(KeyEvent arg0
) {
}
int keyChar = e.getKeyChar();
}else{ // 如果输入的不是数字则屏蔽输入
e.consume(); //关键,屏蔽掉非法输入
}
}
Object source
= e.
getSource();
if(source == btnOk) { // 如果点击了确定按钮,则开始计时
int hour = 0, min = 0;
try {
hour
= Integer.
parseInt(textHour.
getText());
}
try {
min
= Integer.
parseInt(textMin.
getText());
}
startTimer(hour, min);
setVisible(false);
} else if(source == btnCancel) { // 点击取消按钮时取消计时
cancelTimer();
setVisible(false);
} else if(source == btnBack) { // 点击返回按钮时什么也不做,直接关闭设置界面
setVisible(false);
}
}
}
}