[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();
}
}
}
}
[代码运行效果截图]
高级设计师
by: 小蜜锋 发表于:2012-11-15 17:48:41 顶(9) | 踩(0) 回复
代码右上角有一个工具条,请在那里点击复制代码,而不要直接复制。
回复评论