一個精美的java時鐘 (自動換背景 秒針平滑移動)
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.Toolkit; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.image.BufferedImage; import java.net.URL; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar;import javax.swing.JFrame; import javax.swing.JLabel;
/**
- 一個精美的時鐘 (自動換背景 秒針平滑移動)
注意:背景圖片需放在該包的image目錄下(命名:1.jpg...5.jpg) */ public class Clock extends JFrame { // 今天的日期對象 private GregorianCalendar now = new GregorianCalendar(); // 時鐘標簽,上面畫的是圓形時鐘 private ClockLabel clockLabel = new ClockLabel(); // 星期標簽,指示星期 private JLabel weekLabel = new JLabel(); // 日期標簽,指示日期 private JLabel dateLabel = new JLabel(); // 品牌標簽 private JLabel remarkLabel = new JLabel(); // 時間標簽,指示時間 private JLabel timeLabel = new JLabel();
public Clock() {
setTitle("時鐘"); setSize(500, 480); setLocation(((int) Toolkit.getDefaultToolkit().getScreenSize() .getWidth() - 500) / 2, ((int) Toolkit.getDefaultToolkit() .getScreenSize().getHeight() - 480) / 2); init(); setResizable(false);
}
private void init() {
// 初始化品牌標簽 remarkLabel.setText("MyClock"); remarkLabel.setLocation(205, 80); remarkLabel.setSize(100, 30); remarkLabel.setFont(new Font("Bookman Old Style", Font.BOLD, 20)); remarkLabel.setForeground(Color.orange); // 初始化星期標簽 weekLabel.setSize(60, 20); weekLabel.setLocation(315, 190); weekLabel.setForeground(Color.pink); weekLabel.setFont(new Font("Arial Narrow", Font.BOLD, 12)); // 為星期標簽賦值 int week = now.get(Calendar.DAY_OF_WEEK); switch (week) { case 1: weekLabel.setText("SUNDAY"); break; case 2: weekLabel.setText("MONDAY"); break; case 3: weekLabel.setText("TUESDAY"); break; case 4: weekLabel.setText("WEDNESDAY"); break; case 5: weekLabel.setText("THURSDAY"); break; case 6: weekLabel.setText("FRIDAY"); break; case 7: weekLabel.setText("SATURDAY"); break; } // 初始化日期標簽 dateLabel.setSize(20, 20); dateLabel.setLocation(375, 190); dateLabel.setForeground(Color.pink); dateLabel.setFont(new Font("Fixedsys", Font.BOLD, 12)); dateLabel.setText("" + now.get(Calendar.DATE)); // 初始化時間標簽 timeLabel.setSize(500, 30); timeLabel.setLocation(100, 400); timeLabel.setForeground(new Color(0, 64, 128)); timeLabel.setFont(new Font("Fixedsys", Font.PLAIN, 15)); // 將各組件加入到主窗口中 Container con = getContentPane(); con.setBackground(Color.white); con.setLayout(null); con.add(weekLabel); con.add(dateLabel); con.add(remarkLabel); con.add(timeLabel); con.add(clockLabel);
}
public static void main(String[] args) {
Clock clock = new Clock(); clock.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); clock.setVisible(true);
}
// 自定義時鐘標簽,畫一個圓形的時鐘 class ClockLabel extends JLabel implements Runnable {
// 時鐘標簽的寬度和高度 private final int WIDTH = 500; private final int HEIGHT = 440; // 圓形時鐘的X半徑和Y半徑 private final int CIRCLE_X_RADIUS = 150; private final int CIRCLE_Y_RADIUS = 155; // 圓形時鐘的原點 private final int CIRCLE_X = 250; private final int CIRCLE_Y = 200; // 圓形時鐘指針的長度 private final int HOUR_LENGTH = 70; private final int MIN_LENGTH = 100; private final int SEC_LENGTH = 135; // 當前時針所處的角度 double arcHour = 0; // 當前分針所處的角度 double arcMin = 0; // 當前秒針所處的角度 double arcSec = 0; // 顏色的透明度, int alpha = 60; // 標識顏色透明度變化的方向,為true時表示越來越透明,為false時表示月來越不透明 boolean flag = false; // 背景圖片的id,輪換顯示背景圖片時使用 int imageID = 0; // 背景圖片對象數組 Image img[] = new Image[5]; // 背景圖片URL,在該包的image目錄下(命名:1.jpg...5.jpg) URL url[] = new URL[] { ClockLabel.class.getResource("image/1.jpg"), ClockLabel.class.getResource("image/2.jpg"), ClockLabel.class.getResource("image/3.jpg"), ClockLabel.class.getResource("image/4.jpg"), ClockLabel.class.getResource("image/5.jpg"), ClockLabel.class.getResource("image/6.jpg") }; // 一個具有緩沖區的圖像對象 BufferedImage bufferedImage = null; int imageSize = 2 * Math.max(CIRCLE_X_RADIUS, CIRCLE_Y_RADIUS); // 為bufferedImage創建的Graphics對象,用于在bufferedImage上畫圖 Graphics bufferedImageGraphics = null; // 時鐘線程 Thread clockThread = null; // 計數器 int count = 0; public ClockLabel() { // 設置時鐘標簽的大小 this.setSize(WIDTH, HEIGHT); // 獲取時針、分針、秒針當前的角度 arcHour = now.get(Calendar.HOUR) * (360.0 / 12) + now.get(Calendar.MINUTE) * (360.0 / 12 / 60) + now.get(Calendar.SECOND) * (360.0 / 12 / 60 / 60); arcMin = now.get(Calendar.MINUTE) * (360.0 / 60) + now.get(Calendar.SECOND) * (360.0 / 60 / 60); arcSec = now.get(Calendar.SECOND) * (360.0 / 60); // 根據圖片URL創建圖片對象 Toolkit tk = this.getToolkit(); img[0] = tk.createImage(url[0]); img[1] = tk.createImage(url[1]); img[2] = tk.createImage(url[2]); img[3] = tk.createImage(url[3]); img[4] = tk.createImage(url[4]); try { // 使用MediaTracker加載圖片對象 // MediaTracker 類是一個跟蹤多種媒體對象狀態的實用工具類, // 媒體對象可以包括音頻剪輯和圖像,但目前僅支持圖像. MediaTracker mt = new MediaTracker(this); mt.addImage(img[0], 0); mt.addImage(img[1], 0); mt.addImage(img[2], 0); mt.addImage(img[3], 0); mt.addImage(img[4], 0); // 加載媒體跟蹤器中所有的圖像。 mt.waitForAll(); } catch (Exception e) { e.printStackTrace(); } // 創建一個有緩沖的Image對象 bufferedImage = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_ARGB); // 為BufferedImage創建Graphics2D對象, // 以后用該Graphics2D對象畫的圖都會畫在BufferedImage中 bufferedImageGraphics = bufferedImage.createGraphics(); // 啟動線程 clockThread = new Thread(this); clockThread.start(); } public void paint(Graphics g1) { // Graphics2D繼承Graphics,比Graphics提供更豐富的方法 Graphics2D g = (Graphics2D) g1; /** ***畫圓形時鐘的刻度,每6度便有一個刻度**** */ for (int i = 0; i < 360; i = i + 6) { g.setColor(Color.gray); // 設置畫筆的寬度為2 g.setStroke(new BasicStroke(2)); // 畫刻度 if (i % 90 == 0) { // 對于0,3,6,9點位置,使用一個大的刻度 g.setColor(Color.pink); g.setStroke(new BasicStroke(7));// 畫筆寬度為5 // 當起點和終點一樣時,畫的就是點 g.drawLine( CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS), CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS)); } else if (i % 30 == 0) { // 如果角度處于小時的位置,而且還不在0,3,6,9點時,畫紅色的小刻度 g.setColor(Color.orange); g.setStroke(new BasicStroke(3));// 畫筆寬度為3 g.drawLine( CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS), CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS)); } else { // 其他位置就畫小刻度 g.setColor(Color.gray); g.drawLine( CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS), CIRCLE_X + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS), CIRCLE_Y + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS)); } } /** ****** 畫時鐘的指針 ******** */ // 畫時針 Line2D.Double lh = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X + Math.cos((arcHour - 90) * Math.PI / 180) * HOUR_LENGTH, CIRCLE_Y + Math.sin((arcHour - 90) * Math.PI / 180) * HOUR_LENGTH); // 設置畫筆寬度和顏色 g.setStroke(new BasicStroke(8)); g.setColor(Color.pink); // 利用Graphics2D的draw方法畫線 g.draw(lh); // 畫分針 Line2D.Double lm = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X + Math.cos((arcMin - 90) * Math.PI / 180) * MIN_LENGTH, CIRCLE_Y + Math.sin((arcMin - 90) * Math.PI / 180) * MIN_LENGTH); g.setStroke(new BasicStroke(4)); g.setColor(Color.orange); g.draw(lm); // 畫秒針 Line2D.Double ls = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X + Math.cos((arcSec - 90) * Math.PI / 180) * SEC_LENGTH, CIRCLE_Y + Math.sin((arcSec - 90) * Math.PI / 180) * SEC_LENGTH); g.setStroke(new BasicStroke(1)); g.setColor(Color.lightGray); g.draw(ls); /** **** 畫時鐘背景,并將其透明處理 ******* */ // 所有使用bufferedImageGraphics畫的圖像,都畫在bufferedImage上, // drawImage方法的參數含義分別是:背景圖片對象、目標位置第一個角的X、Y坐標、目標位置第二個角的X、Y坐標、 // 源位置第一個角的X、Y坐標、源位置第二個角的X、Y坐標、圖像對象改變時的通知接受者 bufferedImageGraphics.drawImage(img[imageID], 0, 0, imageSize, imageSize, 0, 0, imageSize + 10, imageSize + 10, this); // 將背景圖片透明化 for (int j = 0; j < imageSize; j++) { for (int i = 0; i < imageSize; i++) { // 獲得背景圖像中(i, j)坐標的顏色值 int pix = bufferedImage.getRGB(i, j); Color c = new Color(pix); int R = c.getRed(); int G = c.getGreen(); int B = c.getBlue(); // 通過Color對象的alpha,使顏色透明。 int newpix = new Color(R, G, B, alpha).getRGB(); // 重新設置背景圖像該象素點的顏色 bufferedImage.setRGB(i, j, newpix); } } /** 以上畫背景操作都是畫在bufferedImage上的,這里要將bufferedImage畫在ClockLabel **/ // 將當前用戶剪貼區 Clip 與橢圓區域相交,并將 Clip 設置為所得的交集 g.clip(new Ellipse2D.Double(95, 45, imageSize, imageSize)); g.setColor(Color.white); // 在用戶剪貼區畫bufferedImage g.drawImage(bufferedImage, 95, 45, this); } public void run() { try { while (clockThread != null) { // 計數 count++; // 獲得完整的日期格式 DateFormat df = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL); // 格式化當前時間 String s = df.format(new Date()); timeLabel.setText(s); // 每動一次對時鐘指針的角度進行調整 arcSec += 360.0 / 60 / 10; // 每秒轉6度 arcMin += 360.0 / 60 / 60 / 10; // 每60秒轉6度 arcHour += 360.0 / 12 / 60 / 60 / 10; // 每3600秒轉30度 // 當角度滿一圈時,歸0 if (arcSec >= 360) { arcSec = 0; } if (arcMin >= 360) { arcMin = 0; } if (arcHour >= 360) { arcHour = 0; } // 實現背景透明度漸變 // 從淺入深,再由深入淺。 if (count % 2 == 0) {// 用于背景替換減速 if (flag) { alpha += 1; if (alpha == 60) { flag = !flag; } } else { alpha -= 1; if (alpha == 0) { flag = !flag; // 當透明度變化一個輪回時,換一張背景圖 imageID++; if (imageID == 4) { imageID = 0; } } } if (count >= 2147483647) { // 防溢出 count = 0; } } // 重畫時鐘標簽 repaint(); // 等待0.1秒鐘 Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } }
} }</pre>
本文由用戶 123bt 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!