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; |
|
public class AlarmClock extends JFrame implements ActionListener { |
private static final int LOOP_COUNT = 5 ; // 重复播放的次数 |
private JLabel labelClock, labelAlarm, labelNextAlarm; |
private JButton btnSet, btnClose; |
private SetDialog setDialog; |
private JPanel topPanel, alarmPanel; |
private Timer timer; |
private Clip clip; |
private Calendar alarmCal; |
private boolean timeReached = true ; |
private DateFormat df = new SimpleDateFormat( "HH : mm" ); |
|
public AlarmClock() { |
super ( "闹钟" ); |
} |
|
public void launch() { |
setSize( 400 , 300 ); |
setVisible( true ); |
setDefaultCloseOperation(EXIT_ON_CLOSE); |
|
getContentPane().setLayout( new BorderLayout()); // 利用边界布局将界面分割成上中下三部分 |
labelAlarm = new JLabel( "闹钟定时已到!" ); |
btnClose = new JButton( "确定" ); |
labelNextAlarm = new JLabel(); // 指示下一次闹钟时间 |
alarmPanel = new JPanel( new FlowLayout(FlowLayout.CENTER)); // 顶部提示栏提示闹钟时间已到,和确定按钮 |
alarmPanel.add(labelAlarm); |
alarmPanel.add(btnClose); |
|
topPanel = new JPanel( new GridLayout( 2 , 1 )); |
topPanel.add(alarmPanel); |
topPanel.add(labelNextAlarm); |
alarmPanel.setVisible( false ); // 初始隐藏顶部提示栏 |
|
labelClock = new JLabel(); |
Font font = new Font(Font.SERIF, Font.PLAIN, 48 ); // 中间的倒计时文本用大号字体展示 |
labelClock.setFont(font); |
labelClock.setHorizontalAlignment(JLabel.CENTER); // 文本居中 |
btnSet = new JButton( "设置" ); |
|
getContentPane().add(topPanel, BorderLayout.NORTH); // 界面顶部 |
getContentPane().add(labelClock, BorderLayout.CENTER); // 界面中部 |
getContentPane().add(btnSet, BorderLayout.SOUTH); // 界面底部 |
|
btnSet.addActionListener( this ); // 设置按钮的点击事件 |
btnClose.addActionListener( this ); // 顶部确定按钮的点击事件 |
setLocationRelativeTo( null ); // 界面居中 |
setDialog = new SetDialog( this ); // 初始化设置对话框 |
|
try { // 初始化闹钟声音 |
// 目前发现wav格式的文件是可以支持的,mp3不支持 |
AudioInputStream ais = AudioSystem.getAudioInputStream( |
AlarmClock. class .getResource( "music.wav" )); |
clip = AudioSystem.getClip(); |
clip.open(ais); |
ais.close(); |
int loop = LOOP_COUNT <= 0 ? 1 : LOOP_COUNT; |
final long totalFrames = ais.getFrameLength() * loop; |
clip.addLineListener( new LineListener() { |
public void update(LineEvent e) { |
// 当闹钟音乐播放结束时,自动隐藏顶部提示栏 |
if (e.getFramePosition() >= totalFrames) { |
stopAlarm(); |
} |
} |
}); |
} catch (UnsupportedAudioFileException e) { |
e.printStackTrace(); |
} catch (IOException e) { |
e.printStackTrace(); |
} catch (LineUnavailableException e) { |
e.printStackTrace(); |
} |
initTimer(); |
} |
|
public static void main(String[] args) { |
new AlarmClock().launch(); // 启动主界面 |
} |
|
public void actionPerformed(ActionEvent e) { |
Object source = e.getSource(); |
if (source == btnSet) { // 点击设置按钮时弹出设置界面,以模对话框显示 |
setDialog.setVisible( true ); |
} else if (source == btnClose) { // 点击顶部确定按钮时隐藏顶部提示栏 |
stopAlarm(); |
} |
} |
|
private void initTimer() { |
timer = new Timer(); // 初始化倒计时任务 |
// 开始倒计时 |
timer.scheduleAtFixedRate( new TimerTask() { |
@Override |
public void run() { |
Calendar cal = Calendar.getInstance(); |
int hour = cal.get(Calendar.HOUR_OF_DAY); |
int min = cal.get(Calendar.MINUTE); |
int sec = cal.get(Calendar.SECOND); |
// 设置倒计时文本 |
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 = Calendar.getInstance(); |
alarmCal.set(Calendar.HOUR_OF_DAY, hour); |
alarmCal.set(Calendar.MINUTE, minute); |
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 ); // 隐藏顶部提示栏 |
} |
|
/** |
* 闹钟设置页面 |
*/ |
class SetDialog extends JDialog implements KeyListener, ActionListener { |
private JLabel labelHour, labelMin; |
private JTextField textHour, textMin; |
private JPanel mainPanel, labelPanel, buttonPanel; |
private JButton btnOk, btnCancel, btnBack; |
private Calendar cal = Calendar.getInstance(); |
|
public SetDialog(Frame frame) { |
super (frame); |
setTitle( "设置" ); |
setModal( true ); // 设置为模窗口,就是说在本弹窗未消失时不允许点击主界面。 |
setSize( 300 , 150 ); |
// 显示时分 |
labelHour = new JLabel( "时" ); |
labelMin = new JLabel( "分" ); |
labelHour.setHorizontalAlignment(JLabel.CENTER); |
labelMin.setHorizontalAlignment(JLabel.CENTER); |
textHour = new JTextField(); |
textMin = new JTextField(); |
// 上面的部分用网格布局将各组件以2x2的格子放进去 |
labelPanel = new JPanel( new GridLayout( 2 , 2 )); |
labelPanel.add(labelHour); |
labelPanel.add(labelMin); |
labelPanel.add(textHour); |
labelPanel.add(textMin); |
// 时分输入框添加按键监听,只允许输入数字 |
textHour.addKeyListener( this ); |
textMin.addKeyListener( this ); |
|
// 初始化按钮 |
btnOk = new JButton( "确定" ); |
btnCancel = new JButton( "取消" ); |
btnBack = new JButton( "返回" ); |
// 下面的按钮依次居中放进去 |
buttonPanel = new JPanel( new FlowLayout(FlowLayout.CENTER)); |
buttonPanel.add(btnBack); |
buttonPanel.add(btnCancel); |
buttonPanel.add(btnOk); |
// 初始化主面板,将主面板分割为上下两部分 |
mainPanel = new JPanel( new BorderLayout()); |
mainPanel.add(labelPanel, BorderLayout.CENTER); // 上面显示时分的组件 |
mainPanel.add(buttonPanel, BorderLayout.SOUTH); // 下面排列三个按钮 |
setContentPane(mainPanel); |
// 设置按钮监听 |
btnBack.addActionListener( this ); |
btnOk.addActionListener( this ); |
btnCancel.addActionListener( this ); |
|
cal.add(Calendar.HOUR, 1 ); // 默认设置为当前时间加1小时的整点时间 |
cal.set(Calendar.MINUTE, 0 ); |
int hour = cal.get(Calendar.HOUR_OF_DAY); |
int min = cal.get(Calendar.MINUTE); |
textHour.setText(String.format( "%02d" , hour)); |
textMin.setText(String.format( "%02d" , min)); |
setLocationRelativeTo(frame); |
} |
|
public void keyPressed(KeyEvent arg0) { |
} |
public void keyReleased(KeyEvent arg0) { |
} |
public void keyTyped(KeyEvent e) { |
int keyChar = e.getKeyChar(); |
if (keyChar >= KeyEvent.VK_0 && keyChar <= KeyEvent.VK_9){ |
} else { // 如果输入的不是数字则屏蔽输入 |
e.consume(); //关键,屏蔽掉非法输入 |
} |
} |
|
public void actionPerformed(ActionEvent e) { |
Object source = e.getSource(); |
if (source == btnOk) { // 如果点击了确定按钮,则开始计时 |
int hour = 0 , min = 0 ; |
try { |
hour = Integer.parseInt(textHour.getText()); |
} catch (NumberFormatException e1) { |
} |
try { |
min = Integer.parseInt(textMin.getText()); |
} catch (NumberFormatException e1) { |
} |
startTimer(hour, min); |
setVisible( false ); |
} else if (source == btnCancel) { // 点击取消按钮时取消计时 |
cancelTimer(); |
setVisible( false ); |
} else if (source == btnBack) { // 点击返回按钮时什么也不做,直接关闭设置界面 |
setVisible( false ); |
} |
} |
} |
} |
初级程序员
by: Sube 发表于:2018-09-29 21:13:40 顶(0) | 踩(1) 回复
没有出来钟表
回复评论