使用Swing繪製動態時鐘
本文例項為大家分享了利用Swing繪製一個動態時鐘的具體程式碼,供大家參考,具體內容如下
效果
程式碼在下面,可跳過解析。
前言
程式設計實現一個時鐘
利用Swing繪製一個時鐘,只能是靜態的。利用Calendar類獲取當前的時分秒,然後根據數學公式繪製相應的時鐘就可以了。
如果靜態的時鐘已經足夠你使用,那麼就無須用到執行緒的概念。
如何讓時鐘“動起來”
當然了,動起來肯定是不可能的,但是我們可以利用人眼的視覺,讓時鐘“好像動起來”,其實著很簡單,只要讓當前的影象每隔一秒種重新整理一次就可以了。這樣秒針在動,數字時間也在動,整個時鐘就好像“動起來了”
執行緒
利用執行緒實現重新整理,重新整理間隔是1秒,每次重新整理都先生成當前的時間,然後JVM又會自動呼叫paintComponent方法繪製圖形,這樣就好像時鐘動起來了。
Thread thread = new Thread(){ public void run(){ while(true){ StillClock clock = new StillClock(); MessagePanel messagePanel1=new MessagePanel(clock.getHour()+":"+ clock.getMinute()+":"+clock.getSecond()); //設定顯示居中 messagePanel1.setCentered(true); //設定前景顏色 messagePanel1.setForeground(Color.black); //設定字型 messagePanel1.setFont(new Font("Courier",Font.BOLD,16)); add(clock); add(messagePanel1,BorderLayout.SOUTH); clock.setVisible(true); validate(); //接下來會每隔一秒重繪一次時鐘——即(從frame中將clock元件刪除),因此呼叫validate方法,使容器重新佈置其子元件 try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } clock.setVisible(false); remove(clock); //在父容器中將其刪除 clock.invalidate(); //使容器失效 } } }; thread.start();
執行緒程式碼解析
Thread thread = new Thread(){};
注意結尾使用了分號,既然使用了執行緒,那麼需要重寫它的run方法:
public void run(){}
既然想讓時鐘一直動起來,那麼死迴圈是最好的選擇
while(true){}
在while裡面,每次都先生成當前的時間:
StillClock clock = new StillClock();
這裡生成了一個無參構造的StillClock類,StillClock的無參構造方法裡面會自動生成當前的時間。
注意:這裡的StillClock是我自己定義的,程式碼貼在後面,但是如果不關心他是怎麼實現的,可以直接忽略原理,直接使用,包括程式碼裡面的messagePanel也是一樣的自定義類。
時間生成完了之後,把時鐘圖形、當前時間的字串、佈局位置利用add()方法繪製到螢幕上
add(clock); add(messagePanel1,BorderLayout.SOUTH);
接下來會每隔一秒重繪一次時鐘——即(從frame中將clock元件刪除),因此呼叫validate方法,使容器重新佈置其子元件。
thread.start();
讓執行緒開始工作把。
完整程式碼
DisplayClock.java:
package Test; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; public class DisplayClock extends JFrame { public DisplayClock(){ //建立一個現在的時間 StillClock clock=new StillClock(); //獲取當前的時間 clock.setCurrentTime(); //設定時間的顯示格式 Thread thread = new Thread(){ public void run(){ while(true){ StillClock clock = new StillClock(); MessagePanel messagePanel1=new MessagePanel(clock.getHour()+":"+ clock.getMinute()+":"+clock.getSecond()); //設定顯示居中 messagePanel1.setCentered(true); //設定前景顏色 messagePanel1.setForeground(Color.black); //設定字型 messagePanel1.setFont(new Font("Courier",BorderLayout.SOUTH); clock.setVisible(true); validate(); //接下來會每隔一秒重繪一次時鐘——即(從frame中將clock元件刪除),因此呼叫validate方法,使容器重新佈置其子元件 try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } clock.setVisible(false); remove(clock); //在父容器中將其刪除 clock.invalidate(); //使容器失效 } } }; thread.start(); //佈局預設為BorderLayout,讓顯示資訊在底部(即南邊) } public static void main(String[] args) { DisplayClock frame=new DisplayClock(); frame.setTitle("DisplayClock"); frame.setSize(300,350); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
StillClock.java:
package Test; import sun.util.calendar.Gregorian; import javax.swing.*; import java.awt.*; import java.util.Calendar; import java.util.GregorianCalendar; public class StillClock extends JPanel { public int getHour() { return hour; } public void setHour(int hour) { this.hour = hour; repaint(); } public int getMinute() { return minute; } public void setMinute(int minute) { this.minute = minute; repaint(); } public int getSecond() { return second; } public void setSecond(int second) { this.second = second; repaint(); } private int hour; private int minute; private int second; public StillClock() { setCurrentTime(); } public StillClock(int hour,int minute,int second) { this.hour = hour; this.minute = minute; this.second = second; } //使用Graphics類繪製圖形,需要重寫paintComponent方法 @Override protected void paintComponent(Graphics g) { super.paintComponent(g); //繪製時鐘引數 int clockRadius=(int)(Math.min(getWidth(),getHeight())*0.8*0.5); int xCenter=getWidth()/2; int yCenter=getHeight()/2; //繪製一個圓 g.setColor(Color.BLACK); g.drawOval(xCenter-clockRadius,yCenter-clockRadius,2*clockRadius,2*clockRadius); g.drawString("12",xCenter-5,yCenter-clockRadius+12); g.drawString("9",xCenter-clockRadius+3,yCenter+5); g.drawString("3",xCenter+clockRadius-10,yCenter +3); g.drawString("6",xCenter-3,yCenter+clockRadius-3); //繪製秒針 int sLength=(int)(clockRadius*0.8); int xSecond=(int)(xCenter+sLength*Math.sin(second*(2*Math.PI/60))); int ySecond=(int)(xCenter-sLength*Math.cos(second*(2*Math.PI/60))); g.setColor(Color.red); g.drawLine(xCenter,yCenter,xSecond,ySecond); //繪製分針 int mLength=(int)(clockRadius*0.65); int xMinute=(int)(xCenter+mLength*Math.sin(minute*(2*Math.PI/60))); int yMinute=(int)(xCenter-mLength*Math.cos(minute*(2*Math.PI/60))); g.setColor(Color.blue); g.drawLine(xCenter,xMinute,yMinute); //繪製時針 int hLength=(int)(clockRadius*0.5); int xHour=(int)(xCenter+hLength*Math.sin((hour%12+minute/60.0)*(2*Math.PI/12))); int yHour=(int)(xCenter-hLength*Math.cos((hour%12+minute/60.0)*(2*Math.PI/12))); g.setColor(Color.green); g.drawLine(xCenter,xHour,yHour); } public void setCurrentTime(){ //構造一個日曆類設定當前日期和時間 Calendar calendar=new GregorianCalendar(); //設定時分秒 this.hour=calendar.get(Calendar.HOUR_OF_DAY); this.minute=calendar.get(Calendar.MINUTE); this.second=calendar.get(Calendar.SECOND); } public Dimension getPreferredSize(){ return new Dimension(200,200); } }
messagePanel:
package Test; import javax.swing.*; import java.awt.*; public class MessagePanel extends JPanel { //顯示的資訊 private String message="Welcome to java"; //顯示資訊x的座標 private int xCoordinate=20; //顯示資訊y的座標 private int yCoordinate=20; //資訊是否被顯示在中心部位 private boolean centered; //水平和垂直的移動顯示資訊 private int interval=10; public int getXCoordinate() { return xCoordinate; } public void setXCoordinate(int xCoordinate) { this.xCoordinate = xCoordinate; repaint(); } //無參構造 public MessagePanel() { } //帶參構造 public MessagePanel(String message) { this.message = message; repaint(); } public int getYCoordinate() { return yCoordinate; } public void setYCoordinate(int yCoordinate) { this.yCoordinate = yCoordinate; repaint(); } public boolean isCentered() { return centered; } public void setCentered(boolean centered) { this.centered = centered; repaint(); } public int getInterval() { return interval; } public void setInterval(int interval) { this.interval = interval; repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if(centered){ //設定字型 FontMetrics fm=g.getFontMetrics(); //設定顯示字型 int stringWidth=fm.stringWidth(message); int stringAscent=fm.getAscent(); xCoordinate=getWidth()/2-stringWidth/2; yCoordinate=getHeight()/2+stringAscent/2; } g.drawString(message,xCoordinate,yCoordinate); } //讓資訊往左邊移動 public void moveLeft(){ xCoordinate-=interval; repaint(); } //讓資訊往右邊移動 public void moveRight(){ xCoordinate+=interval; repaint(); } //讓資訊向上移動 public void moveUp(){ yCoordinate+=interval; repaint(); } public void moveDown(){ yCoordinate-=interval; repaint(); } //固定寫法,不必探究 @Override public Dimension getPreferredSize() { return new Dimension(200,30); } }
結束
寫的有些粗糙,有需要的可以根據自己的需求進行更改,比如如何更加穩定的實現動態時鐘,讓時鐘刻度更加精細(根據數學公式增加刻度線即可),希望可以幫助到你。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。