1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
| package Clock;
import sun.audio.AudioPlayer; import sun.audio.AudioStream;
import javax.swing.*; //awt和swing是做界面用的类 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; //io流用于读写文件,包括增删闹钟、打开铃声等等 import java.util.Calendar; //用于获取当前时间的类 import java.util.GregorianCalendar;//标准阳历 import java.util.StringTokenizer; //读取文件转换成计算机语言用的类 /* 1 计时器 要求1:一个带有可视化界面的钟表。 要求2:可以添加若干个闹钟。 要求3:具备持久化功能,关闭程序不能丢失闹钟。 要求4:闹钟是可编辑,可删除的。
实现:先创建一个面板显示闹钟,面板内创建按钮增加闹钟,按钮查看闹钟,按钮删除闹钟 线程间隔1s读取时间和闹钟比较
*/ public class ClockTry extends JFrame implements Runnable { /* 成员变量 */ private JPanel xx; //总的面板 private JComboBox ho; //hour选择时间的下拉框 private JComboBox mi; //min选择分钟的下拉框 private JButton tjnz; //添加闹钟的按钮 private JButton schour; //删除闹钟的按钮 private String filename = "D://homework//java//Gui//src//Clock//0.wav"; //所有的路径改这两个地方就可以了 private String pathname = "D://homework//java//Gui//src//Clock//nz.txt"; // 绝对路径或相对路径都可以,写入文件时演示相对路径,读取以上路径的input.txt文件
private int HOUR; //定义HOUR用于接收按钮按下从下拉框中获取的数据 private int MIN; //同上
int x = 100, y = 100, r = 100; // (x,y)为(0,0)点,表示原点 int h, m, s; // 时,分,秒 double rad = Math.PI / 180; // 1°
private String[][] str= new String[100][2]; //定义二维数组,用于存储以及对小时和分针的操作,暂定为100个闹钟于是定义为【100】【2】 /** *读取文件,每次的增删都需要对数据进行读取,将数据写在面板上也需要读取数据 */ public void readFile() { try (FileReader reader = new FileReader(pathname); //创建一个FilReader对象,将文件读出来,相当于请教一个当地人,当地人了解本地文化,但是语言不通听不懂 BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言,相当于请一个翻译,把当地人读取的东西转换成计算机能懂的东西 ) { String line;
int i =0; while ((line = br.readLine()) != null) { //翻译理解的东西存到line里面 int j =0; StringTokenizer st = new StringTokenizer(line, ":"); //重点:由于存储数据时都是时间,道理来说都是数字,无法区分小时部分和分钟部分 while (st.hasMoreTokens()){ //每读取一次读到的内容 //所以这里用分割符“:”来分割,相应的,后面的写入文件也应该已“:”分割进行写入 str[i][j]=st.nextToken(); //把读到的内容存储在数组里面便于后面的操做——增删 j++; //包括上面的j=0,是将for循环拆分放进while循环中,要不然循环写起来也很麻烦 } //System.out.print(str[i][0]+":"+str[i][1]); 写的时候用来在控制台打印查看效果 //System.out.println(); i++; j = 0; } } catch (IOException e) { e.printStackTrace(); //try……catch抛出异常 } }
/** * 写入TXT文件 */ public void writeFile() { HOUR = Integer.valueOf(ho.getSelectedIndex()); //获取下拉框中的值,存储到HOUR中 MIN = Integer.valueOf(mi.getSelectedIndex()); String x = HOUR + ":" + MIN; try (FileWriter writer = new FileWriter(pathname,true); //同上面的读取,本地人写入,注意:后面的append:true是表示不是重新写,而是在后面追加 BufferedWriter out = new BufferedWriter(writer) //翻译一下再写入 ) {
out.write(HOUR + ":" + MIN + "\r\n"); //这里写入的时候把:写进去了! out.flush(); // 把缓存区内容压入文件,计算机的存储过程,存在缓存区再写入文件 JOptionPane.showMessageDialog(null,"闹钟添加成功!","添加闹钟提醒",JOptionPane.INFORMATION_MESSAGE); //提示框:添加闹钟成功 } catch (IOException e) { e.printStackTrace();
}
}
/** * 删除闹钟,实际上是先将要删除的数据找到移除数组,再将数组重新写入,所以要先读取文件,再重新写入 */ public void shanchuFile() { HOUR = Integer.valueOf(ho.getSelectedIndex()); MIN = Integer.valueOf(mi.getSelectedIndex()); try (FileWriter writer = new FileWriter(pathname); //没有append:true,表示重新写! BufferedWriter out = new BufferedWriter(writer) ) { readFile(); for (int i = 0; i < 100; i++) { if (Integer.valueOf(str[i][0])==HOUR && Integer.valueOf(str[i][1])==MIN){ continue; } else{ out.write(str[i][0]+":"+str[i][1]+"\r\n"); // \r\n即为换行 } }
//out.write("1"+"1"+"\r\n"); // \r\n即为换行 out.flush(); // 把缓存区内容压入文件 } catch (IOException e) { e.printStackTrace(); }catch (NumberFormatException e){ System.out.println("this isn't exist!"); JOptionPane.showMessageDialog(null,"该闹钟已删除!","删除闹钟提醒",JOptionPane.INFORMATION_MESSAGE); //弹窗提示 } }
/* 初始化函数 */ public void init() {
Calendar now = new GregorianCalendar(); //获取当前时间 /* * GregorianCalendar(标准阳历) * 是Calendar(日历)【国际环境下都能运行的程序】 * 的子类 */ s = now.get(Calendar.SECOND) * 6; // 秒针转换成角度:1秒,秒针动一次,转动6° m = now.get(Calendar.MINUTE) * 6; // 分针转换为角度:1分,分针动一次,转动6° h = now.get(Calendar.HOUR) * 30 + now.get(Calendar.MINUTE) / 12 * 6; // 先把分化为小时,再乘以6°,因为分针转12°,时针才会转1°,一小时中间有5格,数学问题 /* * Calendar.HOUR 显示范围:1-12(无论AM还是PM) Calendar.HOUR_OF_DAY 显示范围:1-24(包括PM */
Thread t = new Thread(this); //添加线程,线程目标是整个程序,this t.start(); //线程就绪 }
public void paint(Graphics g) { //awt中的方法,因为要时时显示闹钟,所以不得不使用绘画的方式,不断重绘 super.paint(g); /* * paint(g)函数会重绘图像,要加上super.paint(g),表示在原来图像的基础上,再画图。 * 如果不加super.paint(g),重绘时,会将原有的绘制清空,再根据paing(g)函数绘制。 */
g.setColor(Color.BLACK); //设置画笔颜色——黑色 g.drawOval(x, y, r * 2, r * 2);// 画表 /* drawOval(x,y,width,height)以矩形恰好框住椭圆,矩形左上角的顶点坐标为(x,y) */
// 秒针 int x1 = (int) (90 * Math.sin(rad * s)); int y1 = (int) (90 * Math.cos(rad * s)); g.drawLine(r+x, r+y, r+x + x1, r +y- y1); /* drawLine(a,b,c,d) (a,b)为起始坐标 (c,d)为终点坐标 */
// 分针 x1 = (int) (80 * Math.sin(rad * m)); y1 = (int) (80 * Math.cos(rad * m)); g.drawLine(r+x, r+y, r +x+ x1, r+y - y1);
// 时针 x1 = (int) (60 * Math.sin(rad * h)); y1 = (int) (60 * Math.cos(rad * h)); g.drawLine(r+x, r+y, r+x + x1, r +y- y1);
// 画数字 int d = 30; for (int i = 1; i <= 12; i++) { x1 = (int) ((r - 10) * Math.sin(rad * d)); y1 = (int) ((r - 10) * Math.cos(rad * d)); g.drawString(String.valueOf(i), r+x + x1, r+y - y1); //字符型的数据才能画 d += 30; }
// 画刻度 d = 0; for (int i = 1; i <= 60; i++) { x1 = (int) ((r - 2) * Math.sin(rad * d)); y1 = (int) ((r - 2) * Math.cos(rad * d)); g.drawString(".", r+x + x1, r +y- y1); //画的是点,表示刻度 d += 6; } // 显示时间 Calendar now1 = new GregorianCalendar(); int a, b, c; a = now1.get(Calendar.HOUR_OF_DAY); //获取当前的小时 b = now1.get(Calendar.MINUTE); //获取当前的分钟 c = now1.get(Calendar.SECOND); //获取当前的秒钟 g.drawString(a + ":" + b + ":" + c, 175, 330); //将时间也画到面板上 g.drawString("全部闹钟:",100,350); //全部闹钟
try (FileReader reader = new FileReader(pathname); BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言 ) { String line;
int i =0; while ((line = br.readLine()) != null) { int j =0; StringTokenizer st = new StringTokenizer(line, ":"); while (st.hasMoreTokens()){ str[i][j]=st.nextToken(); j++; } g.drawString(str[i][0]+":"+str[i][1]+"\n",180+(i/10)*70,350+15*(i-(i/10)*10)); //貌似重新写了一下readfile的方法,其实是有区别的,这里是读取以后画出来 //qbnz.setText(str[i][0]+":"+str[i][1]+"\n"); //System.out.print(str[i][0]+":"+str[i][1]); //System.out.println(); i++; j = 0; } } catch (IOException z) { z.printStackTrace(); } }
// 实现Runnable,实现implement Runnable就务必实现run方法,使线程运行 public void run() { while (true) { try { Thread.sleep(1000);// 间隔一秒 } catch (Exception ex) { } s += 6; // 秒针每次走6° if (s >= 360) { s = 0; // 秒针归零 m += 6; if (m == 72 || m == 144 || m == 288) { h += 6; // 分针走72°,时针走6° 分针的12倍,时针走一次 }
if (m >= 360) { m = 0; // 分针归零 h += 6; } if (h >= 360) { h = 0; // 时针归零 } }
this.repaint(); // 重新绘制 //this.readFile(); this.alert(); //将闹钟加入到线程当中 }}
public void alert(){ Calendar now1 = new GregorianCalendar(); int a, b; a = now1.get(Calendar.HOUR_OF_DAY); b = now1.get(Calendar.MINUTE); //这里没有获取秒针是因为闹钟不看秒针。。。。。 try (FileReader reader = new FileReader(pathname); BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言 ) { String line; String[][] str= new String[100][2]; int i =0; while ((line = br.readLine()) != null) { int j =0; StringTokenizer st = new StringTokenizer(line, ":"); while (st.hasMoreTokens()){ str[i][j]=st.nextToken(); j++; } if (a==Integer.valueOf(str[i][0]) && b==Integer.valueOf(str[i][1])){ //读取后与获得的时间比较,如果闹钟存在,就响 try{ InputStream in = new FileInputStream("D://homework//java//Gui//src//Clock//0.wav");//FIlename 是你加载的声音文件如(“game.wav”) AudioStream as = new AudioStream(in); //和读取文件类似的原理,经翻译之后才播放出来 AudioPlayer.player.start(as); //用静态成员player.start播放音乐 } catch(FileNotFoundException e){ System.out.print("FileNotFoundException "); } catch(IOException e){ System.out.print("有错误!"); } } i++; j = 0; } } catch (IOException z) { z.printStackTrace(); } }
//初始化界面 public void launchFrame(){ xx = new JPanel(); //插入一个面板 String[] hours = new String[24]; //长度为24的数组用于存储小时 for (int i = 0; i < hours.length; i++) { hours[i]=i+""; //循环对hour进行赋值 } ho = new JComboBox(hours); //将hour加入到下拉框中 ho.setSize(50,40); //设置大小好像没用 String[] mins = new String[60]; //同理,这是分钟的地方 for (int i = 0; i < mins.length; i++) { mins[i]=i+""; //分钟赋值 } mi = new JComboBox(mins); //分钟下拉框 mi.setSize(50,40); tjnz = new JButton(); //添加闹钟的按钮,拼音首字母 tjnz.setText("添加到闹钟"); //按钮上显示的文字 tjnz.setSize(100,40); schour = new JButton(); //删除闹钟的按钮 schour.setText("从闹钟中删除"); //按钮上显示的文字 schour.setSize(100,40);
/** * 将按钮下拉框啥的加入到面板中 */ xx.add(ho); xx.add(mi); xx.add(tjnz); xx.add(schour); this.add(xx); //将面板加入到this对象中,要不然面板就不显示 tjnz.addActionListener(new ActionListener() { //添加按钮的功能 @Override //重写的标识,务必要会 public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub HOUR = Integer.valueOf(ho.getSelectedIndex()); MIN = Integer.valueOf(mi.getSelectedIndex()); //获取到时分后 writeFile(); //写入txt文件保存为闹钟 readFile(); //再读取,这样才能时时更新面板上的全部闹钟 }});
schour.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub HOUR = Integer.valueOf(ho.getSelectedIndex()); MIN = Integer.valueOf(mi.getSelectedIndex()); shanchuFile(); //这里是删除闹钟的按钮功能 readFile(); }});
this.setTitle("小闹钟"); //设置窗口标题 this.setVisible(true); //设置窗口不隐身 this.setSize(700,500); //设置窗口大小 this.setLocation(500, 250); //设置窗口位置,相对于桌面左上角 this.init(); //调用初始化函数进行初始化 this.alert(); //this.run(); //重复调用run()方法结果是秒针一次走12° this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); //设置窗口叉号的功能,点击就关闭程序 }
public static void main(String[] args) { ClockTry c = new ClockTry(); //main方法,必有的成分,创建主类对象, c.launchFrame(); //调用初始化面板的方法,简化了本该在main方法中写的代码
}}
|