JAVA可視化鬧鍾源碼


概述

一些同學的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; //
 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 }}

運行效果

2

3

此版本為第一次嘗試,后續有時間會繼續更新版本


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM