概述 一些同學的Java課設有這樣一個問題,比較感興趣就做了一下 功能介紹: 1、可增加鬧鐘 2、可刪除鬧鐘 3、時間到了響鈴 4、關閉鬧鐘不會丟失鬧鐘(因為鬧鐘存儲在txt文件中,不會因程式關閉就終止) 缺點 1、沒有使用多線程,鬧鐘響起時只能等待1分鐘或者關閉程式 2、界面設計不夠美觀,後期有時 ...
概述
一些同學的Java課設有這樣一個問題,比較感興趣就做了一下
功能介紹:
1、可增加鬧鐘
2、可刪除鬧鐘
3、時間到了響鈴
4、關閉鬧鐘不會丟失鬧鐘(因為鬧鐘存儲在txt文件中,不會因程式關閉就終止)
缺點
1、沒有使用多線程,鬧鐘響起時只能等待1分鐘或者關閉程式
2、界面設計不夠美觀,後期有時間會進行修改,重新設計
3、沒有鬧鐘修改的功能,雖然可以通過增刪來達到修改的目的,但功能仍然屬於空缺範圍
1 package Clock; 2 3 import sun.audio.AudioPlayer; 4 import sun.audio.AudioStream; 5 6 import javax.swing.*; //awt和swing是做界面用的類 7 import java.awt.*; 8 import java.awt.event.ActionEvent; 9 import java.awt.event.ActionListener; 10 import java.awt.event.WindowAdapter; 11 import java.awt.event.WindowEvent; 12 import java.io.*; //io流用於讀寫文件,包括增刪鬧鐘、打開鈴聲等等 13 import java.util.Calendar; //用於獲取當前時間的類 14 import java.util.GregorianCalendar;//標準陽曆 15 import java.util.StringTokenizer; //讀取文件轉換成電腦語言用的類 16 /* 17 1 計時器 18 要求1:一個帶有可視化界面的鐘錶。 19 要求2:可以添加若幹個鬧鐘。 20 要求3:具備持久化功能,關閉程式不能丟失鬧鐘。 21 要求4:鬧鐘是可編輯,可刪除的。 22 23 實現:先創建一個面板顯示鬧鐘,面板內創建按鈕增加鬧鐘,按鈕查看鬧鐘,按鈕刪除鬧鐘 24 線程間隔1s讀取時間和鬧鐘比較 25 26 */ 27 public class ClockTry extends JFrame implements Runnable { 28 /* 成員變數 */ 29 private JPanel xx; //總的面板 30 private JComboBox ho; //hour選擇時間的下拉框 31 private JComboBox mi; //min選擇分鐘的下拉框 32 private JButton tjnz; //添加鬧鐘的按鈕 33 private JButton schour; //刪除鬧鐘的按鈕 34 private String filename = "D://homework//java//Gui//src//Clock//0.wav"; //所有的路徑改這兩個地方就可以了 35 private String pathname = "D://homework//java//Gui//src//Clock//nz.txt"; // 絕對路徑或相對路徑都可以,寫入文件時演示相對路徑,讀取以上路徑的input.txt文件 36 37 private int HOUR; //定義HOUR用於接收按鈕按下從下拉框中獲取的數據 38 private int MIN; //同上 39 40 int x = 100, y = 100, r = 100; // (x,y)為(0,0)點,表示原點 41 int h, m, s; // 時,分,秒 42 double rad = Math.PI / 180; // 1° 43 44 private String[][] str= new String[100][2]; //定義二維數組,用於存儲以及對小時和分針的操作,暫定為100個鬧鐘於是定義為【100】【2】 45 /** 46 *讀取文件,每次的增刪都需要對數據進行讀取,將數據寫在面板上也需要讀取數據 47 */ 48 public void readFile() { 49 try (FileReader reader = new FileReader(pathname); //創建一個FilReader對象,將文件讀出來,相當於請教一個當地人,當地人瞭解本地文化,但是語言不通聽不懂 50 BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言,相當於請一個翻譯,把當地人讀取的東西轉換成電腦能懂的東西 51 ) { 52 String line; 53 54 int i =0; 55 while ((line = br.readLine()) != null) { //翻譯理解的東西存到line裡面 56 int j =0; 57 StringTokenizer st = new StringTokenizer(line, ":"); //重點:由於存儲數據時都是時間,道理來說都是數字,無法區分小時部分和分鐘部分 58 while (st.hasMoreTokens()){ //每讀取一次讀到的內容 //所以這裡用分割符“:”來分割,相應的,後面的寫入文件也應該已“:”分割進行寫入 59 str[i][j]=st.nextToken(); //把讀到的內容存儲在數組裡面便於後面的操做——增刪 60 j++; //包括上面的j=0,是將for迴圈拆分放進while迴圈中,要不然迴圈寫起來也很麻煩 61 } 62 //System.out.print(str[i][0]+":"+str[i][1]); 寫的時候用來在控制台列印查看效果 63 //System.out.println(); 64 i++; 65 j = 0; 66 } 67 } catch (IOException e) { 68 e.printStackTrace(); //try……catch拋出異常 69 } 70 } 71 72 73 /** 74 * 寫入TXT文件 75 */ 76 public void writeFile() { 77 HOUR = Integer.valueOf(ho.getSelectedIndex()); //獲取下拉框中的值,存儲到HOUR中 78 MIN = Integer.valueOf(mi.getSelectedIndex()); 79 String x = HOUR + ":" + MIN; 80 try (FileWriter writer = new FileWriter(pathname,true); //同上面的讀取,本地人寫入,註意:後面的append:true是表示不是重新寫,而是在後面追加 81 BufferedWriter out = new BufferedWriter(writer) //翻譯一下再寫入 82 ) { 83 84 out.write(HOUR + ":" + MIN + "\r\n"); //這裡寫入的時候把:寫進去了! 85 out.flush(); // 把緩存區內容壓入文件,電腦的存儲過程,存在緩存區再寫入文件 86 JOptionPane.showMessageDialog(null,"鬧鐘添加成功!","添加鬧鐘提醒",JOptionPane.INFORMATION_MESSAGE); //提示框:添加鬧鐘成功 87 } catch (IOException e) { 88 e.printStackTrace(); 89 90 } 91 92 } 93 94 95 /** 96 * 刪除鬧鐘,實際上是先將要刪除的數據找到移除數組,再將數組重新寫入,所以要先讀取文件,再重新寫入 97 */ 98 public void shanchuFile() { 99 HOUR = Integer.valueOf(ho.getSelectedIndex()); 100 MIN = Integer.valueOf(mi.getSelectedIndex()); 101 try (FileWriter writer = new FileWriter(pathname); //沒有append:true,表示重新寫! 102 BufferedWriter out = new BufferedWriter(writer) 103 ) { 104 readFile(); 105 for (int i = 0; i < 100; i++) { 106 if (Integer.valueOf(str[i][0])==HOUR && Integer.valueOf(str[i][1])==MIN){ 107 continue; 108 } 109 else{ 110 out.write(str[i][0]+":"+str[i][1]+"\r\n"); // \r\n即為換行 111 } 112 } 113 114 //out.write("1"+"1"+"\r\n"); // \r\n即為換行 115 out.flush(); // 把緩存區內容壓入文件 116 } catch (IOException e) { 117 e.printStackTrace(); 118 }catch (NumberFormatException e){ 119 System.out.println("this isn't exist!"); 120 JOptionPane.showMessageDialog(null,"該鬧鐘已刪除!","刪除鬧鐘提醒",JOptionPane.INFORMATION_MESSAGE); //彈窗提示 121 } 122 } 123 124 /* 初始化函數 */ 125 public void init() { 126 127 Calendar now = new GregorianCalendar(); //獲取當前時間 128 /* 129 * GregorianCalendar(標準陽曆) 130 * 是Calendar(日曆)【國際環境下都能運行的程式】 131 * 的子類 132 */ 133 s = now.get(Calendar.SECOND) * 6; // 秒針轉換成角度:1秒,秒針動一次,轉動6° 134 m = now.get(Calendar.MINUTE) * 6; // 分針轉換為角度:1分,分針動一次,轉動6° 135 h = now.get(Calendar.HOUR) * 30 + now.get(Calendar.MINUTE) / 12 * 6; // 先把分化為小時,再乘以6°,因為分針轉12°,時針才會轉1°,一小時中間有5格,數學問題 136 /* 137 * Calendar.HOUR 顯示範圍:1-12(無論AM還是PM) Calendar.HOUR_OF_DAY 顯示範圍:1-24(包括PM 138 */ 139 140 Thread t = new Thread(this); //添加線程,線程目標是整個程式,this 141 t.start(); //線程就緒 142 } 143 144 public void paint(Graphics g) { //awt中的方法,因為要時時顯示鬧鐘,所以不得不使用繪畫的方式,不斷重繪 145 super.paint(g); 146 /* 147 * paint(g)函數會重繪圖像,要加上super.paint(g),表示在原來圖像的基礎上,再畫圖。 148 * 如果不加super.paint(g),重繪時,會將原有的繪製清空,再根據paing(g)函數繪製。 149 */ 150 151 g.setColor(Color.BLACK); //設置畫筆顏色——黑色 152 g.drawOval(x, y, r * 2, r * 2);// 畫表 153 /* drawOval(x,y,width,height)以矩形恰好框住橢圓,矩形左上角的頂點坐標為(x,y) */ 154 155 // 秒針 156 int x1 = (int) (90 * Math.sin(rad * s)); 157 int y1 = (int) (90 * Math.cos(rad * s)); 158 g.drawLine(r+x, r+y, r+x + x1, r +y- y1); 159 /* drawLine(a,b,c,d) (a,b)為起始坐標 (c,d)為終點坐標 */ 160 161 // 分針 162 x1 = (int) (80 * Math.sin(rad * m)); 163 y1 = (int) (80 * Math.cos(rad * m)); 164 g.drawLine(r+x, r+y, r +x+ x1, r+y - y1); 165 166 // 時針 167 x1 = (int) (60 * Math.sin(rad * h)); 168 y1 = (int) (60 * Math.cos(rad * h)); 169 g.drawLine(r+x, r+y, r+x + x1, r +y- y1); 170 171 // 畫數字 172 int d = 30; 173 for (int i = 1; i <= 12; i++) { 174 x1 = (int) ((r - 10) * Math.sin(rad * d)); 175 y1 = (int) ((r - 10) * Math.cos(rad * d)); 176 g.drawString(String.valueOf(i), r+x + x1, r+y - y1); //字元型的數據才能畫 177 d += 30; 178 } 179 180 // 畫刻度 181 d = 0; 182 for (int i = 1; i <= 60; i++) { 183 x1 = (int) ((r - 2) * Math.sin(rad * d)); 184 y1 = (int) ((r - 2) * Math.cos(rad * d)); 185 g.drawString(".", r+x + x1, r +y- y1); //畫的是點,表示刻度 186 d += 6; 187 } 188 // 顯示時間 189 Calendar now1 = new GregorianCalendar(); 190 int a, b, c; 191 a = now1.get(Calendar.HOUR_OF_DAY); //獲取當前的小時 192 b = now1.get(Calendar.MINUTE); //獲取當前的分鐘 193 c = now1.get(Calendar.SECOND); //獲取當前的秒鐘 194 g.drawString(a + ":" + b + ":" + c, 175, 330); //將時間也畫到面板上 195 g.drawString("全部鬧鐘:",100,350); //全部鬧鐘 196 197 try (FileReader reader = new FileReader(pathname); 198 BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言 199 ) { 200 String line; 201 202 int i =0; 203 while ((line = br.readLine()) != null) { 204 int j =0; 205 StringTokenizer st = new StringTokenizer(line, ":"); 206 while (st.hasMoreTokens()){ 207 str[i][j]=st.nextToken(); 208 j++; 209 } 210 g.drawString(str[i][0]+":"+str[i][1]+"\n",180+(i/10)*70,350+15*(i-(i/10)*10)); //貌似重新寫了一下readfile的方法,其實是有區別的,這裡是讀取以後畫出來 211 //qbnz.setText(str[i][0]+":"+str[i][1]+"\n"); 212 //System.out.print(str[i][0]+":"+str[i][1]); 213 //System.out.println(); 214 i++; 215 j = 0; 216 } 217 } catch (IOException z) { 218 z.printStackTrace(); 219 } 220 } 221 222 223 // 實現Runnable,實現implement Runnable就務必實現run方法,使線程運行 224 public void run() { 225 while (true) { 226 try { 227 Thread.sleep(1000);// 間隔一秒 228 } catch (Exception ex) { 229 } 230 s += 6; // 秒針每次走6° 231 if (s >= 360) { 232 s = 0; // 秒針歸零 233 m += 6; 234 if (m == 72 || m == 144 || m == 288) { 235 h += 6; // 分針走72°,時針走6° 分針的12倍,時針走一次 236 } 237 238 if (m >= 360) { 239 m = 0; // 分針歸零 240 h += 6; 241 } 242 if (h >= 360) { 243 h = 0; // 時針歸零 244 } 245 } 246 247 248 this.repaint(); // 重新繪製 249 //this.readFile(); 250 this.alert(); //將鬧鐘加入到線程當中 251 }} 252 253 public void alert(){ 254 Calendar now1 = new GregorianCalendar(); 255 int a, b; 256 a = now1.get(Calendar.HOUR_OF_DAY); 257 b = now1.get(Calendar.MINUTE); //這裡沒有獲取秒針是因為鬧鐘不看秒針。。。。。 258 try (FileReader reader = new FileReader(pathname); 259 BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言 260 ) { 261 String line; 262 String[][] str= new String[100][2]; 263 int i =0; 264 while ((line = br.readLine()) != null) { 265 int j =0; 266 StringTokenizer st = new StringTokenizer(line, ":"); 267 while (st.hasMoreTokens()){ 268 str[i][j]=st.nextToken(); 269 j++; 270 } 271 if (a==Integer.valueOf(str[i][0]) && b==Integer.valueOf(str[i][1])){ //讀取後與獲得的時間比較,如果鬧鐘存在,就響 272 try{ 273 InputStream in = new FileInputStream("D://homework//java//Gui//src//Clock//0.wav");//FIlename 是你載入的聲音文件如(“game.wav”) 274 AudioStream as = new AudioStream(in); //和讀取文件類似的原理,經翻譯之後才播放出來 275 AudioPlayer.player.start(as); //用靜態成員player.start播放音樂 276 } catch(FileNotFoundException e){ 277 System.out.print("FileNotFoundException "); 278 } catch(IOException e){ 279 System.out.print("有錯誤!"); 280 } 281 } 282 i++; 283 j = 0; 284 } 285 } catch (IOException z) { 286 z.printStackTrace(); 287 } 288 } 289 290 //初始化界面 291 public void launchFrame(){ 292 xx = new JPanel(); //插入一個面板 293 String[] hours = new String[24]; //長度為24的數組用於存儲小時 294 for (int i = 0; i < hours.length; i++) { 295 hours[i]=i+""; //迴圈對hour進行賦值 296 } 297 ho = new JComboBox(hours); //將hour加入到下拉框中 298 ho.setSize(50,40); //設置大小好像沒用 299 String[] mins = new String[60]; //同理,這是分鐘的地方 300 for (int i = 0; i < mins.length; i++) { 301 mins[i]=i+""; //分鐘賦值 302 } 303 mi = new JComboBox(mins); //分鐘下拉框 304 mi.setSize(50,40); 305 tjnz = new JButton(); //添加鬧鐘的按鈕,拼音首字母 306 tjnz.setText("添加到鬧鐘"); //按鈕上顯示的文字 307 tjnz.setSize(100,40); 308 schour = new JButton(); //刪除鬧鐘的按鈕 309 schour.setText("從鬧鐘中刪除"); //按鈕上顯示的文字 310 schour.setSize(100,40); 311 312 /** 313 * 將按鈕下拉框啥的加入到面板中 314 */ 315 xx.add(ho); 316 xx.add(mi); 317 xx.add(tjnz); 318 xx.add(schour); 319 this.add(xx); //將面板加入到this對象中,要不然面板就不顯示 320 tjnz.addActionListener(new ActionListener() { //添加按鈕的功能 321 @Override //重寫的標識,務必要會 322 public void actionPerformed(ActionEvent e) { 323 // TODO Auto-generated method stub 324 HOUR = Integer.valueOf(ho.getSelectedIndex()); 325 MIN = Integer.valueOf(mi.getSelectedIndex()); //獲取到時分後 326 writeFile(); //寫入txt文件保存為鬧鐘 327 readFile(); //再讀取,這樣才能時時更新面板上的全部鬧鐘 328 }}); 329 330 schour.addActionListener(new ActionListener() { 331 @Override 332 public void actionPerformed(ActionEvent e) { 333 // TODO Auto-generated method stub 334 HOUR = Integer.valueOf(ho.getSelectedIndex()); 335 MIN = Integer.valueOf(mi.getSelectedIndex()); 336 shanchuFile(); //這裡是刪除鬧鐘的按鈕功能 337 readFile(); 338 }}); 339 340 this.setTitle("小鬧鐘"); //設置視窗標題 341 this.setVisible(true); //設置視窗不隱身 342 this.setSize(700,500); //設置視窗大小 343 this.setLocation(500, 250); //設置視窗位置,相對於桌面左上角 344 this.init(); //調用初始化函數進行初始化 345 this.alert(); 346 //this.run(); //重覆調用run()方法結果是秒針一次走12° 347 this.addWindowListener(new WindowAdapter() { 348 @Override 349 public void windowClosing(WindowEvent e) { 350 System.exit(0); 351 } 352 }); //設置視窗叉號的功能,點擊就關閉程式 353 } 354 355 356 357 public static void main(String[] args) { 358 ClockTry c = new ClockTry(); //main方法,必有的成分,創建主類對象, 359 c.launchFrame(); //調用初始化面板的方法,簡化了本該在main方法中寫的代碼 360 361 }}
運行效果
此版本為第一次嘗試,後續有時間會繼續更新版本