效果如下:
步骤:
一.在项目中创建一个继承JFrame类的MainFrame窗体类。一个继承Jlable类,并实现Runnable接口的自定义标签类SnowFlakeLable及一个背景面板类BackgroundPanel。
二.在标签类SnowFlakeLable中实现Runable接口的run()方法中,每隔一小段时间就对自定义标签在父级容器中的位置进行改变,从而实现雪花飘落的效果。
三.在MainFrame窗体类中,为背景面板类BackgroundPanel的实例添加鼠标移动事件,用于向背景面板中添加自定义雪花标签对象。
代码如下:
BackgroundPanel类
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
/**
* 背景面板
*/
public class BackgroundPanel extends JPanel {
private static final long serialVersionUID = 5260642571525243284L;
private Image image;// 背景图像
public BackgroundPanel() {
setOpaque(false);// 透明
setLayout(null);// 绝对布局
}
public void setImage(Image image) {
this.image = image;// 设置图像
}
protected void paintComponent(Graphics g) {
if (image != null) {
g.drawImage(image, 0, 0, this);// 绘制图像
}
super.paintComponent(g);// 调用超类的方法
}
}
MainFrame类
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Cursor;
public class MainFrame extends JFrame {
private static final long serialVersionUID = 1L;
private BackgroundPanel backgroundPanel = null;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame thisClass = new MainFrame();
thisClass.setVisible(true);
}
});
}
public MainFrame() {
super();
setTitle("雪花飘落动画");
setSize(628, 441);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Image image = new ImageIcon(getClass().getResource("/image/cursor.png")).getImage();// 创建图像对象
Cursor cursor = getToolkit().createCustomCursor(image, new Point(),"魔棒");// 创建鼠标光标对象
setCursor(cursor);// 指定鼠标光标
setResizable(false);// 不允许改变窗体大小
backgroundPanel = new BackgroundPanel();// 创建背景面板
// 为背景面板指定图像
backgroundPanel.setImage(new ImageIcon(getClass().getResource("/image/bg.jpg")).getImage());
backgroundPanel.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {// 鼠标移动事件
SnowFlakeLabel snow = new SnowFlakeLabel();// 创建雪花飘落标签
Point point = e.getPoint();// 获得鼠标位置
snow.setLocation(point);// 指定雪花在背景面板上的位置
backgroundPanel.add(snow);// 将雪花添加到背景面板上
}
});
getContentPane().setLayout(new BorderLayout());// 指定窗体内容面板为边界布局
getContentPane().add(backgroundPanel, BorderLayout.CENTER);// 在窗体内容面板上添加背景面板
}
}
SnowFlakeLabel类
import java.awt.*;
import javax.swing.*;
/**
* @author: 张阳阳
*/
public class SnowFlakeLabel extends JLabel implements Runnable {
private final static ImageIcon snow = new ImageIcon(SnowFlakeLabel.class
.getResource("/image/snowflake.png"));//获取源文件
private int width = snow.getIconWidth();// 宽度
private int height = snow.getIconHeight();// 高度
/**
* 构造方法
*/
public SnowFlakeLabel() {
setSize(new Dimension(width, height));// 初始化大小
setIcon(snow);// 指定图标
new Thread(this).start();// 创建并启动线程
}
public void run() {
Container parent = getParent();// 获取父容器对象
Point myPoint = getLocation();// 获取初始位置
while (true) {// 循环读取父容器对象
if (parent == null) {
try {
Thread.sleep(50);// 线程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
myPoint = getLocation();// 获取初始位置
parent = getParent();// 获取父容器对象
} else {// 如果已经获取到父容器
break;// 跳出循环
}
}
int sx = myPoint.x;// X坐标
int sy = myPoint.y;// Y坐标
int stime = (int) (Math.random() * 30 + 10);// 随机移动速度
int parentHeight = parent.getHeight();// 容器高度
while (parent.isVisible() && sy < parentHeight - height) {
setLocation(sx, sy);// 指定位置
try {
Thread.sleep(stime);// 线程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
sy += 2;// 垂直偏移2个像素
}
}
}
image下的图片: