此案例来源于书本是我对书中程序的改建与说明:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.lang.reflect.Field;
import javax.swing.JLabel;
/**展示面板*/
@SuppressWarnings("serial")
public class BallFrame extends JFrame {
private JPanel Pane ;// 背景面板
private Ball ball = null;// 窗体提供一个小球
测试方法:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BallFrame thisClass = new BallFrame();
thisClass
.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thisClass.setVisible(true);
}
});
}
/**
* 构造方法
*/
public BallFrame() {
super();
initialize();// 初始程序界面
}
/**
* 初始化程序界面
*/
private void initialize() {
this.setSize(512, 384);// 设置窗体大小
this.setResizable(false);// 禁止调整窗体大小
this.setContentPane(getJContentPane());// 添加内容面板
// 设置窗体标题文本
this.setTitle("窗体中的乒乓球----鼠标左键添加,右键减少");
}
/**
* 背景面板
*
* @return javax.swing.JPanel
*/
private JPanel getJContentPane() {
if (Pane == null) {
ball = new Ball();// 创建第一个小球
// 设置小球位置与大小
ball.setBounds(new Rectangle(121, 67, 20, 20));
// 创建背景面板
Pane = new BGPanel();
// 背景面板使用null布局
Pane.setLayout(null);
Pane.add(ball, null);// 添加第一个小球到背景面板
// 为背景面板添加鼠标事件监听器
Pane.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// 获取面板中控件的数量
int count = Pane.getComponentCount();
// 如果是单击鼠标左键,则添加小球
if (e.getButton() == MouseEvent.BUTTON1) {
if (count <= 20) {// 限制小球数量为20
Ball ball = new Ball();// 创建新的小球对象
Point point = e.getPoint();// 获取鼠标当前位置
ball.setLocation(point);// 设置小球为鼠标位置
Pane.add(ball);// 添加小球到面板
} else {// 否则
// 提示小球太多
JOptionPane.showMessageDialog(null,
"球太多啦");
}
} else {// 如果单击鼠标右键
if (count < 1) {// 如果面板中没有控件
// 对话框提示信息
JOptionPane.showMessageDialog(null,
"没有球啦");
return;
}
// 移除面板中的第一个控件
Pane.remove(0);
// 重新绘制面板
Pane.repaint();
}
}
});
}
return Pane;
}
}
小球一个内部类:
class Ball extends JLabel implements Runnable {
private int r = 10;// 小球半径
private int width = r * 2;// 球宽度
private int height = r * 2;// 球高度
private Color ballColor = Color.BLACK;// 默认颜色
/**
* 构造方法
*/
public Ball() {
// 初始化大小
setSize(new Dimension(width, height));
setPreferredSize(new Dimension(width, height));
// 反射获取Color类的所有成员变量数组
Field[] fields = Color.class.getFields();
// 随机生成数组下标索引
int index = (int) (Math.random() * fields.length);
try {
// 获取指定下标索引的成员变量
Object object = fields[index].get(null);
// 判断是否Color类的实例对象
if (object instanceof Color) {
// 改变默认颜色
ballColor = (Color) object;
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 启动小球跳跃线程
new Thread(this).start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(ballColor);// 设置默认颜色
g.fillOval(0, 0, width, height);// 绘制球体
}
@Override
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 step = (int) (Math.random() * 10) % 3 + 1;// 移动步进
int dx = (Math.random() * 100) >= 50 ? step : -step;// 水平步进值
step = (int) (Math.random() * 10) % 3 + 1;// 移动步进
int dy = (Math.random() * 100) >= 50 ? step : -step;// 垂直步进值
// 随机移动速度
int stime = (int) (Math.random() * 80 + 10);
while (parent.isVisible()) {
int parentWidth = parent.getWidth();// 容器宽度
int parentHeight = parent.getHeight();// 容器高度
setLocation(sx, sy);
try {
Thread.sleep(stime);
} catch (InterruptedException e) {
e.printStackTrace();
}
sx = sx + dx * 5;// 水平坐标偏移5个像素
sy = sy + dy * 5;// 垂直坐标偏移5个像素
// 检测垂直边界
if (sy > parentHeight - height - 15 || sy - 20 < 0)
dy = -dy;// 防止坐标超出垂直边界
// 检测水平边界
if (sx > parentWidth - width - 25 || sx - 20 < 0)
dx = -dx;// 防止坐标超出水平边界
}
}
}
此程序运行无错后上传
如有错误我会尽快修改后上传